আমি কি কুকিগুলিকে একটি WKWebView দ্বারা ব্যবহার করতে সেট করতে পারি?


135

আমি থেকে একটি বিদ্যমান অ্যাপ্লিকেশন সুইচ করার চেষ্টা করছি UIWebViewকরার WKWebView। বর্তমান অ্যাপটি ব্যবহারকারীদের লগইন / সেশনের বাইরে পরিচালনা করে webviewএবং এর মধ্যে cookiesপ্রমাণীকরণের জন্য প্রয়োজনীয় সেট করে NSHTTPCookieStore। দুর্ভাগ্যবশত নতুন WKWebViewব্যবহার করে না cookiesথেকে NSHTTPCookieStorage। এটি অর্জনের অন্য কোনও উপায় আছে কি?

উত্তর:


186

শুধুমাত্র iOS 11+ এর জন্য সম্পাদনা করুন

ব্যবহার WKHTTPCookieStore :

let cookie = HTTPCookie(properties: [
    .domain: "example.com",
    .path: "/",
    .name: "MyCookieName",
    .value: "MyCookieValue",
    .secure: "TRUE",
    .expires: NSDate(timeIntervalSinceNow: 31556926)
])! 

webView.configuration.websiteDataStore.httpCookieStore.setCookie(cookie)

যেহেতু আপনি HTTPCookeStorage থেকে এগুলি টানছেন, আপনি এটি করতে পারেন:

let cookies = HTTPCookieStorage.shared.cookies ?? []
for cookie in cookies {
    webView.configuration.websiteDataStore.httpCookieStore.setCookie(cookie)
}

আইওএস 10 এবং নীচের জন্য পুরানো উত্তর

আপনার যদি আপনার কুকিগুলির প্রাথমিক লোড অনুরোধে সেট করার প্রয়োজন হয় তবে আপনি সেগুলি এনএসমেটেবল URL অনুরোধে সেট করতে পারেন। কারণ কুকিজ কেবলমাত্র একটি বিশেষ বিন্যাসিত অনুরোধ শিরোনাম তাই এটি অর্জন করা যেতে পারে:

WKWebView * webView = /*set up your webView*/
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://example.com/index.html"]];
[request addValue:@"TeskCookieKey1=TeskCookieValue1;TeskCookieKey2=TeskCookieValue2;" forHTTPHeaderField:@"Cookie"];
// use stringWithFormat: in the above line to inject your values programmatically
[webView loadRequest:request];

আপনার যদি কুকিজ সেট করার জন্য পৃষ্ঠায় পরবর্তী এজেএক্স অনুরোধগুলির প্রয়োজন হয়, তবে ডকুমেন্টের শুরুতে জাভাস্ক্রিপ্টের মাধ্যমে প্রোগ্রামটিভালি মানগুলি সেট করার জন্য ডাব্লুউকিউসারস্ক্রিপ্ট ব্যবহার করে এটি অর্জন করা যেতে পারে:

WKUserContentController* userContentController = WKUserContentController.new;
WKUserScript * cookieScript = [[WKUserScript alloc] 
    initWithSource: @"document.cookie = 'TeskCookieKey1=TeskCookieValue1';document.cookie = 'TeskCookieKey2=TeskCookieValue2';"
    injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
// again, use stringWithFormat: in the above line to inject your values programmatically
[userContentController addUserScript:cookieScript];
WKWebViewConfiguration* webViewConfig = WKWebViewConfiguration.new;
webViewConfig.userContentController = userContentController;
WKWebView * webView = [[WKWebView alloc] initWithFrame:CGRectMake(/*set your values*/) configuration:webViewConfig];

এই দুটি কৌশলটির সংমিশ্রণে আপনাকে কুকি মানগুলি নেটিভ অ্যাপ ল্যান্ড থেকে ওয়েব ভিউ ল্যান্ডে স্থানান্তর করতে পর্যাপ্ত সরঞ্জাম দেওয়া উচিত give আপনি আরও তথ্য পেতে পারেন যদি আরও কিছু উন্নত কুকিজের প্রয়োজন হয় তবে আপনি মজিলার পৃষ্ঠায় কুকি জাভাস্ক্রিপ্ট এপিআইতে

হ্যাঁ, এটি সাফল্য পেয়েছে যে অ্যাপল ইউআইউইউভিউ ভিউর অনেকগুলি অভিনবতাকে সমর্থন করছে না । তারা কখনই তাদের সমর্থন করবে কিনা তা নিশ্চিত নন, তবে আশা করি তারা শীঘ্রই এটি অর্জন করবেন। আশাকরি এটা সাহায্য করবে!


1
পরবর্তী অনুরোধগুলির জন্য কুকিজ ইনজেক্ট করার সেরা জায়গাটি কোথায়? উদাহরণস্বরূপ প্রাথমিক পৃষ্ঠার লোডটি উপরের উত্তরে coveredেকে দেওয়া হয়েছে, তবে যদি সেই পৃষ্ঠায় লিঙ্কগুলি থাকে যা একই ডোমেনে নিয়ে যায় এবং অনুরোধের সাথে একই কুকিগুলির দরকার হয় তবে কী হবে? didStartProvisionalNavigation?
মেসন জি। ঝুইটি

1
দুঃখিত এটি আপনার পক্ষে কাজ করছে না। আমার মনে, যতক্ষণ ডোমেন একই থাকে ততক্ষণ কোনও সমস্যা হওয়া উচিত নয়। আপনি যে কোডটি অনুরোধটি লোড করেছেন সেই লিঙ্কটি একই ডোমেনটির দিকে ইঙ্গিত করছে এমন কোডটি আপনি কি ডাবল চেক করতে পারেন? এছাড়াও, কুকিজগুলিকেও একটি নির্দিষ্ট "পথে" সীমাবদ্ধ করা যেতে পারে। হয়তো কিছু সমস্যা সৃষ্টি করছে?
ম্যাটার

11
নোট করুন যে কুকিগুলি সেট করার জাভাস্ক্রিপ্ট কৌশল "কেবলমাত্র এইচটিটিপি" কুকিজের জন্য কাজ করবে না।
আহমেদ নাসের

1
উপরের পদ্ধতিটি দুর্দান্ত কাজ করে ... তবে আমি পরবর্তীকালে এজেএক্স কলগুলিতে কুকিজের সদৃশ দেখতে পেলাম (কেবল একবারে নকল হয়েছে)।
দুর্গা ভুন্ডাভল্লি

1
@ অ্যাক্সেল ৯২ কাজটি নিশ্চিত করা আপনার ওয়েবভিউ থেকে আপনার সার্ভারে করা প্রথম অনুরোধটি একটি প্রতিক্রিয়া পেয়েছে যা স্পষ্টভাবে ওয়েবভিউকে এইচটিপিটিউলি পতাকা দিয়ে আবার কুকিজ সেট করতে বলে (যেমন: প্রতিক্রিয়াতে কুকিজটি আবার সেট করুন)। ওয়েবভিউ সূচনা করার সময় আপনি সেই একমাত্র উদ্দেশ্যে একটি বিশেষ এপিআই তৈরি করতে পারেন, তারপরে সাফল্যের উপর সাধারণত ওয়েবভিউ ব্যবহার করুন।
আহমেদ নাসের

64

এই উত্তরটি খেলে (যা দুর্দান্তভাবে কার্যকর হয়েছিল :) আমাদের কয়েকটি পরিবর্তন করতে হয়েছিল:

  • সেই ডোমেনগুলির মধ্যে ব্যক্তিগত কুকির তথ্য ফাঁস না করে একাধিক ডোমেন মোকাবেলার জন্য আমাদের ওয়েব ভিউ দরকার
  • সুরক্ষিত কুকিজকে সম্মান জানাতে আমাদের এটি দরকার
  • যদি সার্ভারটি কোনও কুকির মান পরিবর্তন করে তবে আমরা আমাদের অ্যাপটিকে এটি সম্পর্কে জানতে চাই NSHTTPCookieStorage
  • সার্ভার যদি কোনও কুকির মান পরিবর্তন করে তবে আমরা চাই না যে আপনি যখন কোনও লিঙ্ক / এজেএক্স ইত্যাদি অনুসরণ করেন তখন আমাদের স্ক্রিপ্টগুলি আবার এটির মূল মানটিতে পুনরায় সেট করতে দেয় don't

সুতরাং আমরা আমাদের কোডটি এটি হতে পরিবর্তন করেছি;

একটি অনুরোধ তৈরি করা হচ্ছে

NSMutableURLRequest *request = [originalRequest mutableCopy];
NSString *validDomain = request.URL.host;
const BOOL requestIsSecure = [request.URL.scheme isEqualToString:@"https"];

NSMutableArray *array = [NSMutableArray array];
for (NSHTTPCookie *cookie in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]) {
    // Don't even bother with values containing a `'`
    if ([cookie.name rangeOfString:@"'"].location != NSNotFound) {
        NSLog(@"Skipping %@ because it contains a '", cookie.properties);
        continue;
    }

    // Is the cookie for current domain?
    if (![cookie.domain hasSuffix:validDomain]) {
        NSLog(@"Skipping %@ (because not %@)", cookie.properties, validDomain);
        continue;
    }

    // Are we secure only?
    if (cookie.secure && !requestIsSecure) {
        NSLog(@"Skipping %@ (because %@ not secure)", cookie.properties, request.URL.absoluteString);
        continue;
    }

    NSString *value = [NSString stringWithFormat:@"%@=%@", cookie.name, cookie.value];
    [array addObject:value];
}

NSString *header = [array componentsJoinedByString:@";"];
[request setValue:header forHTTPHeaderField:@"Cookie"];

// Now perform the request...

এটি নিশ্চিত করে যে অন্য ডোমেনের জন্য ভাগ করা স্টোরেজ থেকে কোনও কুকিজ না পাঠানো এবং কোনও সুরক্ষিত অনুরোধে কোনও সুরক্ষিত কুকিজ না পাঠিয়ে প্রথম অনুরোধটিতে সঠিক কুকিজ সেট রয়েছে।

আরও অনুরোধ সঙ্গে ডিল

আমাদের অন্যান্য অনুরোধের কুকি সেট আছে তাও আমাদের নিশ্চিত করতে হবে। এটি এমন একটি স্ক্রিপ্ট ব্যবহার করে করা হয়েছে যা দস্তাবেজ লোডে চলমান যা কোনও কুকি সেট আছে কিনা তা পরীক্ষা করে এবং যদি মান না করে সেট করে NSHTTPCookieStorage

// Get the currently set cookie names in javascriptland
[script appendString:@"var cookieNames = document.cookie.split('; ').map(function(cookie) { return cookie.split('=')[0] } );\n"];

for (NSHTTPCookie *cookie in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]) {
    // Skip cookies that will break our script
    if ([cookie.value rangeOfString:@"'"].location != NSNotFound) {
        continue;
    }

    // Create a line that appends this cookie to the web view's document's cookies
    [script appendFormat:@"if (cookieNames.indexOf('%@') == -1) { document.cookie='%@'; };\n", cookie.name, cookie.wn_javascriptString];
}

WKUserContentController *userContentController = [[WKUserContentController alloc] init];
WKUserScript *cookieInScript = [[WKUserScript alloc] initWithSource:script
                                                      injectionTime:WKUserScriptInjectionTimeAtDocumentStart
                                                   forMainFrameOnly:NO];
[userContentController addUserScript:cookieInScript];

...

// Create a config out of that userContentController and specify it when we create our web view.
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
config.userContentController = userContentController;

self.webView = [[WKWebView alloc] initWithFrame:webView.bounds configuration:config];

কুকির পরিবর্তনগুলি নিয়ে কাজ করা

আমাদের একটি কুকির মান পরিবর্তন করার সাথে সার্ভারের সাথেও ডিল করতে হবে। এর অর্থ আমাদের আপডেট করার জন্য তৈরি করা ওয়েব ভিউ থেকে ফিরে কল করতে অন্য স্ক্রিপ্ট যুক্ত করা NSHTTPCookieStorage

WKUserScript *cookieOutScript = [[WKUserScript alloc] initWithSource:@"window.webkit.messageHandlers.updateCookies.postMessage(document.cookie);"
                                                       injectionTime:WKUserScriptInjectionTimeAtDocumentStart
                                                    forMainFrameOnly:NO];
[userContentController addUserScript:cookieOutScript];

[userContentController addScriptMessageHandler:webView
                                          name:@"updateCookies"];

এবং পরিবর্তিত কোনও কুকিজ আপডেট করার জন্য ডেলিগেট পদ্ধতিটি বাস্তবায়ন করে, এটি নিশ্চিত করে যে আমরা কেবলমাত্র বর্তমান ডোমেন থেকে কুকিজ আপডেট করছি!

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    NSArray<NSString *> *cookies = [message.body componentsSeparatedByString:@"; "];
    for (NSString *cookie in cookies) {
        // Get this cookie's name and value
        NSArray<NSString *> *comps = [cookie componentsSeparatedByString:@"="];
        if (comps.count < 2) {
            continue;
        }

        // Get the cookie in shared storage with that name
        NSHTTPCookie *localCookie = nil;
        for (NSHTTPCookie *c in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:self.wk_webView.URL]) {
            if ([c.name isEqualToString:comps[0]]) {
                localCookie = c;
                break;
            }
        }

        // If there is a cookie with a stale value, update it now.
        if (localCookie) {
            NSMutableDictionary *props = [localCookie.properties mutableCopy];
            props[NSHTTPCookieValue] = comps[1];
            NSHTTPCookie *updatedCookie = [NSHTTPCookie cookieWithProperties:props];
            [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:updatedCookie];
        }
    }
}

আমরা WKWebView কে আলাদাভাবে ব্যবহার করি এমন প্রতিটি জায়গার সাথে আমাদের মোকাবিলা না করে আমাদের কুকি সমস্যাগুলি সমাধান করে বলে মনে হয়। আমরা এখন এই ওয়েব কোডটি কেবলমাত্র আমাদের ওয়েব ভিউ তৈরি করতে সহায়ক হিসাবে ব্যবহার করতে পারি এবং এটি NSHTTPCookieStorageআমাদের জন্য স্বচ্ছভাবে আপডেট হয় ।


সম্পাদনা: দেখা যাচ্ছে আমি এনএসএইচটিটিপি কুকিতে একটি ব্যক্তিগত বিভাগ ব্যবহার করেছি - এখানে কোডটি রয়েছে:

- (NSString *)wn_javascriptString {
    NSString *string = [NSString stringWithFormat:@"%@=%@;domain=%@;path=%@",
                        self.name,
                        self.value,
                        self.domain,
                        self.path ?: @"/"];

    if (self.secure) {
        string = [string stringByAppendingString:@";secure=true"];
    }

    return string;
}

6
আমি আপনার কোডটি ডাব্লুউইউভিউ ভিউয়ের একটি সাবক্লাসে আবৃত করেছি। এটি নির্দ্বিধায় github.com/haifengkao/YWebView দেখুন
হাই ফেং কাও

যদি আপনার কুকিগুলিতে = মান চিহ্ন থাকে? এই কাজ করবে?
আইওএস এডডিক্টেড

@IOSAddected আমিও তাই মনে করি । আপনার মানটি যদি a=bআপনি কুকি স্ট্রিংয়ের সাথে শেষ করেন name=a=b;domain=.example.com;path=/- আমি বিশ্বাস করি যে মানটি স্প্লিট হয় ;এবং তারপরে কী = মান জোড়ায় প্রথমটি বিভক্ত হয় =। যদিও আমি এটি পরীক্ষা করব :)
ডিনবম্বর্ন

আপনার প্রতিক্রিয়া আমাকে অনেক সাহায্য করেছে, আমি চাই তবে আপনার পোস্টে কিছু যুক্ত করুন, আপনার আপডেট পদ্ধতিটি ব্যবহার করার সময় বেশ কয়েকটি ঝুঁকি রয়েছে, কিছু জেএস ফ্রেমওয়ার্কগুলি এমন কুকি তৈরি করতে পারে যার একই নাম কিন্তু আলাদা ডোমেন রয়েছে এবং আপনি যদি এটি আপডেট করার চেষ্টা করেন জেএস পদ্ধতি ব্যবহার করে আপনার একটি ভুল মান সহ কুকি আপডেট করার উচ্চ ঝুঁকি রয়েছে। এছাড়াও আমাদের জন্য জেএস কুকির স্ট্রিংটি তার সুরক্ষিত পতাকাটি ছিনিয়ে নিতে হয়েছিল, কারণ আমাদের সার্ভারটি HT ও https এর মধ্যে দুষ্টু পুনঃনির্দেশ তৈরি করে, কিছু দুষ্টু প্রান্তের ক্ষেত্রে সুরক্ষিত কুকিগুলি কিছু পৃষ্ঠায় উপস্থিত না করে causing
রিকার্ডোডুয়ার্টে

আমি আসলে আমার মনে হয় যে আমি এই সংস্থার সাথে ছিলাম তার সাথে লাইভ হওয়ার পরে এটিতে কিছু ডোমেন সুরক্ষা যুক্ত করতে হবে। আমরা কখনই (আফাইক) সুরক্ষিত / অনিরাপদ সমস্যায় পড়িনি - দুঃস্বপ্নের মতো শোনাচ্ছে!
ডিনবম্বর্ন

42

কুকিজগুলি WKWebViewতৈরির আগে কনফিগারেশনে সেট করা উচিত । তা না হলে, এমনকি WKHTTPCookieStoreএর setCookieপরিপূরণ হ্যান্ডলার, কুকিজ নির্ভরযোগ্যভাবে ওয়েব দর্শন সিঙ্ক করা হবে না। এটি ডক্স অন থেকে এই লাইনে ফিরে যায়WKWebViewConfiguration

@NSCopying var configuration: WKWebViewConfiguration { get }

যে @NSCopying একটি গভীর কপি কিছুটা হয়। বাস্তবায়নটি আমার বাইরে but এটি অ্যাপের আর্কিটেকচারকে জটিল করে তুলতে পারে কারণ একটি ভিউ শুরু করা একটি অ্যাসিক্রোনাস প্রক্রিয়াতে পরিণত হয়। আপনি এই জাতীয় কিছু দিয়ে শেষ করব

extension WKWebViewConfiguration {
    /// Async Factory method to acquire WKWebViewConfigurations packaged with system cookies
    static func cookiesIncluded(completion: @escaping (WKWebViewConfiguration?) -> Void) {
        let config = WKWebViewConfiguration()
        guard let cookies = HTTPCookieStorage.shared.cookies else {
            completion(config)
            return
        }
        // Use nonPersistent() or default() depending on if you want cookies persisted to disk
        // and shared between WKWebViews of the same app (default), or not persisted and not shared
        // across WKWebViews in the same app.
        let dataStore = WKWebsiteDataStore.nonPersistent()
        let waitGroup = DispatchGroup()
        for cookie in cookies {
            waitGroup.enter()
            dataStore.httpCookieStore.setCookie(cookie) { waitGroup.leave() }
        }
        waitGroup.notify(queue: DispatchQueue.main) {
            config.websiteDataStore = dataStore
            completion(config)
        }
    }
}

এবং তারপরে এটি ব্যবহার করার মতো

override func loadView() {
    view = UIView()
    WKWebViewConfiguration.cookiesIncluded { [weak self] config in
        let webView = WKWebView(frame: .zero, configuration: webConfiguration)
        webView.load(request)
        self.view = webView
    }
}

উপরের উদাহরণটি শেষ সম্ভাব্য মুহুর্ত পর্যন্ত দেখার সৃষ্টিটিকে স্থগিত করে, অন্য সমাধানটি হবে কনফিগার বা ওয়েবভিউ ভালভাবে তৈরি করা এবং ভিউ কন্ট্রোলার তৈরির আগে অ্যাসিনক্রোনাস প্রকৃতি পরিচালনা করা।

একটি চূড়ান্ত নোট: আপনি একবার এই ওয়েবভিউ তৈরি করার পরে, আপনি এটিকে বুনোতে রেখে দিয়েছেন, এই উত্তরে বর্ণিত পদ্ধতি ব্যবহার না করে আপনি আরও কুকি যুক্ত করতে পারবেন না । WKHTTPCookieStoreObserverকমপক্ষে কুকিজের পরিবর্তনগুলি পর্যবেক্ষণ করতে আপনি এপিআই ব্যবহার করতে পারেন । সুতরাং যদি কোনও সেশন কুকি ওয়েবভিউতে আপডেট হয়ে যায়, আপনি HTTPCookieStorageযদি চান তবে এই নতুন কুকি সহ সিস্টেমটিকে ম্যানুয়ালি আপডেট করতে পারেন ।

এর আরও তথ্যের জন্য, এই 2017 ডাব্লুডাব্লুডিসি সেশন কাস্টম ওয়েব সামগ্রী লোডিং এ 18:00 এ যান । এই অধিবেশনটির শুরুতে, একটি ছদ্মবেশী কোডের নমুনা রয়েছে যা সম্পূর্ণরূপে হ্যান্ডলারে ওয়েব ভিউ তৈরি করা উচিত এই বিষয়টি বাদ দেয়।

cookieStore.setCookie(cookie!) {
    webView.load(loggedInURLRequest)
}

18:00 এ লাইভ ডেমো এটি স্পষ্ট করে।

মোজাভে বিটা 7 এবং আইওএস 12 বিটা 7 হিসাবে সম্পাদনা করুন , আমি কুকিজের সাথে অনেক বেশি ধারাবাহিক আচরণ দেখছি seeing setCookie(_:)পদ্ধতি এমনকি পরে সেটিং কুকিজ অনুমোদন মনে হচ্ছে WKWebViewতৈরি করা হয়েছে। আমি এটা গুরুত্বপূর্ণ যদিও খুঁজে করেনি স্পর্শ করবেনprocessPool এ সব পরিবর্তনশীল। কোনও অতিরিক্ত পুল তৈরি না করা এবং যখন সম্পত্তিটি একা ভাল রেখে দেওয়া হয় তখন কুকি সেটিং কার্যকারিতা সর্বোত্তম কাজ করে। আমি মনে করি এটি নিরাপদ বলে মনে করি যে ওয়েবকিটে কিছু বাগের কারণে আমাদের সমস্যা হচ্ছে।


দেখে মনে হচ্ছে কুকি হ্যান্ডলিং / সেটিং মোজাভে 10.14 বিটা 3 এবং আইওএস 12 বিটা 3
নটিস্লার

6
খুব গভীর এবং আন্ডাররেটেড উত্তরে
নিকোলস ক্যারাসকো

1
আমি ইতোমধ্যে আইওএস 12 এ ইতিমধ্যে লোড হওয়া WKWebView দিয়ে এই সমস্যাটি নিয়ে আসছি। কখনও কখনও সেটকুকি () আসলে সঙ্গে সঙ্গে ডাব্লুউইউভিউ ভিউয়ের সাথে সরাসরি সিঙ্ক করা হবে, কখনও কখনও এটি হ্যান্ডলিংটিকে কিছুটা বিক্ষিপ্ত করে তুলবে না
বিএমজোনস

রাডারটি স্থির দাবি করার পরেও আমি এখনও সমস্যাগুলি দেখেছি, তবে খুব কম ঘন ঘন। আপনি কুকি ব্যর্থতা কত ঘন ঘন দেখছেন? আপনার যদি পুনরুত্পাদনযোগ্য, ছোট্ট যথেষ্ট প্রকল্প থাকে তবে আমি এখানে একটি ওয়েবকিট বাগ জমা দেওয়ার জন্য সত্যিই সুপারিশ করব: ওয়েবকিট.আর / রেকর্ডিং-বুগস আপনি ব্র্যাডি আইডসনকে (সুন্দরভাবে) অ্যাপলের একটি ওয়েবকিট আর্কিটেক্টকে টুইট করতে পারেন যিনি এই ধরণের প্রতি খুব প্রতিক্রিয়াশীল is রিপোর্ট এবং বাগ।
nteissler

এটি সঠিক উত্তর - প্রতিটি ইউআরএলউইকুয়েস্টে কুকিজকে শিরোনাম ক্ষেত্র হিসাবে ম্যানুয়ালি অনুবাদ করার দরকার নেই, এটি এখানে ঠিক আছে যে সেটকুকি () এখানে বর্ণিত হিসাবে ব্যবহার করা দরকার।
গিলিয়াম লরেন্ট

25

আমার জন্য কাজ

func webView(webView: WKWebView, decidePolicyForNavigationAction navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) {
    let headerFields = navigationAction.request.allHTTPHeaderFields
    var headerIsPresent = contains(headerFields?.keys.array as! [String], "Cookie")

    if headerIsPresent {
        decisionHandler(WKNavigationActionPolicy.Allow)
    } else {
        let req = NSMutableURLRequest(URL: navigationAction.request.URL!)
        let cookies = yourCookieData
        let values = NSHTTPCookie.requestHeaderFieldsWithCookies(cookies)
        req.allHTTPHeaderFields = values
        webView.loadRequest(req)

        decisionHandler(WKNavigationActionPolicy.Cancel)
    }
}

অসাধারণ হ্যাক, বিশেষত আইআরকিউএস কীভাবে বিদ্যমান ডাব্লুউইউবিউ ভিউতে কোনও কুকিকে ওভাররাইড করার বিষয়ে। একমাত্র গোচাটাই হ'ল পূর্ববর্তী ডব্লিউএন নেভিগেশনকি বাসি হয়ে গেছে। অন্যান্য কোডটি পুরানোটির পক্ষে নিরর্থকভাবে অপেক্ষা করছে।
বেসজেন

2
এটা কি সঠিক? এটি প্রশংসা করুন কিছু পরিস্থিতিতে কাজ করতে পারে। তবে এই প্রতিনিধি পদ্ধতির দায়িত্ব - সিদ্ধান্তের নীতিমালা নীতিমালা নির্ধারণ করা; অনুরোধটি আসলে লোড করার জন্য নয়। এর আগে দীক্ষা করা হয়েছিল। কোন ক্ষেত্রে, এটি কি অনুরোধটি দুইবার লোড হওয়ার কারণ নয়?
সর্বাধিক ম্যাকলিয়ড

2
@ ম্যাক্সম্যাকলিয়ড এই elseঅবস্থাতে তিনি ক্লোজারটি কল decisionHandlerকরছেন .cancelযাতে webviewএটি প্রাথমিক অনুরোধটি আসলে লোড করে না। পরে loadRequestবলা হয় elseঅবস্থা এই প্রতিনিধি পদ্ধতি যা অনুরোধের জন্য আবার ডাকা হবে এবং এটি মধ্যে যেতে হবে ifশর্ত কারণ Cookieহেডার উপস্থিত থাকবে।
হালিল_জি

2
যদিও এটি কার্যকর হবে না যখন প্রাথমিক অনুরোধটিতে ইতিমধ্যে কিছু কুকিজ সেট আছে, কারণ এটি কখনই elseশর্তে যাবে না ।
হালিল_জি

মনে রাখবেন যে এটি 1) প্রতিটি পরিস্থিতির জন্য কাজ করে না - উদাহরণস্বরূপ, যখন ওয়েব ভিউ ফ্রেম লোড হয় 2) নিরাপদ নয় - এটি তৃতীয় পক্ষের
ইউআরএলকে

20

HTTPCookieStorage থেকে সমস্ত কুকি ইনজেকশনের জন্য সুইট-এ আমার ম্যাটরস সমাধানের সংস্করণ । এটি প্রধানত একটি ব্যবহারকারী সেশন তৈরি করতে একটি প্রমাণীকরণ কুকি ইনজেকশনের জন্য করা হয়েছিল।

public func setupWebView() {
    let userContentController = WKUserContentController()
    if let cookies = HTTPCookieStorage.shared.cookies {
        let script = getJSCookiesString(for: cookies)
        let cookieScript = WKUserScript(source: script, injectionTime: .atDocumentStart, forMainFrameOnly: false)
        userContentController.addUserScript(cookieScript)
    }
    let webViewConfig = WKWebViewConfiguration()
    webViewConfig.userContentController = userContentController

    self.webView = WKWebView(frame: self.webViewContainer.bounds, configuration: webViewConfig)
}

///Generates script to create given cookies
public func getJSCookiesString(for cookies: [HTTPCookie]) -> String {
    var result = ""
    let dateFormatter = DateFormatter()
    dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
    dateFormatter.dateFormat = "EEE, d MMM yyyy HH:mm:ss zzz"

    for cookie in cookies {
        result += "document.cookie='\(cookie.name)=\(cookie.value); domain=\(cookie.domain); path=\(cookie.path); "
        if let date = cookie.expiresDate {
            result += "expires=\(dateFormatter.stringFromDate(date)); "
        }
        if (cookie.secure) {
            result += "secure; "
        }
        result += "'; "
    }
    return result
}

লোকেল বিন্যাসটি সঠিক কিনা তা নিশ্চিত করতে এই লাইনটি যুক্ত করা আরও ভাল:dateFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
বুবুকু

এটাকে কোথায় ডাকবো?
markhorrocks

এটি আমার পক্ষে সুইফট 4-এ (সামান্য সামঞ্জস্য সহ) সূক্ষ্মভাবে কাজ করেছে
ফ্রেডেরিক অ্যাডা

এটি আমার পক্ষে দুর্দান্ত কাজ করে, তবে আমি কেবল দ্বিতীয়বার সাইটটি পরিদর্শন করেছি (প্রথমবারের মতো কুকিজ সেট করা নেই) - কেউ কি এই জুড়ে আসবে?
মিঃ ক্রিস বার্কার

প্রথম লোড ত্রুটি দিন দ্বিতীয় লোডের কাজ :( সমস্যাটি কী হতে পারে?
শওকেত শেখ

10

কুকি সেট করুন

self.webView.evaluateJavaScript("document.cookie='access_token=your token';domain='your domain';") { (data, error) -> Void in
        self.webView.reload()
}

কুকি মুছুন

self.webView.evaluateJavaScript("document.cookie='access_token=';domain='your domain';") { (data, error) -> Void in
        self.webView.reload()
}

9

সুইফট 3 আপডেট:

func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
    if let urlResponse = navigationResponse.response as? HTTPURLResponse,
       let url = urlResponse.url,
       let allHeaderFields = urlResponse.allHeaderFields as? [String : String] {
       let cookies = HTTPCookie.cookies(withResponseHeaderFields: allHeaderFields, for: url)
       HTTPCookieStorage.shared.setCookies(cookies , for: urlResponse.url!, mainDocumentURL: nil)
       decisionHandler(.allow)
    }
}

1
হাই, আপনিও কুকিজ পেতে কোড যুক্ত করতে পারেন HTTPCookieStorage.shared?
মার্খোররোকস

ওয়েবকিউ দ্বারা করা প্রতিটি অনুরোধে কুকিজ যুক্ত করার জন্য আমি ডাব্লুউইউবিউ ভিউয়ের একমাত্র উপায় পেয়েছি
চিকোভিটজ

প্রতিক্রিয়াতে এটিতে যদি স্বতন্ত্র কুকি থাকে তবে আপনি এইভাবে কুকিজের মান পেতে পারেন না।
মস্তিষ্ক

1
এটি কেবলমাত্র কুকিগুলিকেই httpcookies স্টোরেজে ফিরে আসছে যেখানে ডাব্লুউইউবিউভিউয়ের জন্য কুকি সেটআপ করার কোডটি কোথায়?
শওকেত শেখ 24'18

8

এখানে বিভিন্ন উত্তর সন্ধান করার পরে এবং কোনও সাফল্য না পাওয়ার পরে, আমি ওয়েবকিট ডকুমেন্টেশনের মাধ্যমে ঝাঁকিয়েছি এবং requestHeaderFieldsস্থির পদ্ধতিতে হোঁচট খেয়েছি HTTPCookie, যা কুকির একটি অ্যারেটিকে একটি শিরোলেখের ক্ষেত্রের জন্য উপযুক্ত বিন্যাসে রূপান্তরিত করে। আপডেট করার ক্ষেত্রে ম্যাটারের অন্তর্দৃষ্টি দিয়ে এটি একত্রিত করাURLRequest কুকি হেডার সঙ্গে এটি লোড সামনে আমাকে ফিনিস লাইন মাধ্যমে পেয়েছিলাম।

সুইফট ৪.১, ৪.২, ৫.০:

var request = URLRequest(url: URL(string: "https://example.com/")!)
let headers = HTTPCookie.requestHeaderFields(with: cookies)
for (name, value) in headers {
    request.addValue(value, forHTTPHeaderField: name)
}

let webView = WKWebView(frame: self.view.frame)
webView.load(request)

এটিকে আরও সরল করতে, একটি এক্সটেনশন ব্যবহার করুন:

extension WKWebView {
    func load(_ request: URLRequest, with cookies: [HTTPCookie]) {
        var request = request
        let headers = HTTPCookie.requestHeaderFields(with: cookies)
        for (name, value) in headers {
            request.addValue(value, forHTTPHeaderField: name)
        }

        load(request)
    }
}

এখন এটি হয়ে যায়:

let request = URLRequest(url: URL(string: "https://example.com/")!)
let webView = WKWebView(frame: self.view.frame)
webView.load(request, with: cookies)

আপনি যদি কেবল একটি ড্রপ-ইন সমাধান চান তবে এই এক্সটেনশনটি লায়নহার্ট এক্সটেনশনেও উপলব্ধ । চিয়ার্স!


1
@ শৌকেতশেখ হুম, কোন পরিস্থিতিতে এটি কাজ করে না?
ড্যান লোয়েহেনার্জ

আমি সিমুলেটার আইওএস 8 টি পরীক্ষা করে দেখে মনে হচ্ছে এটি কুকিজ প্রেরণ করছে না। আমি এটি ডাবল চেক করেছি।
শওকেত শেখ 25'18

আমি আমার উত্তর পোস্ট করেছি আপনি @ ড্যান
শেখ

7

আইওএস ১১-এ, আপনি এখনই কুকি পরিচালনা করতে পারেন :), এই সেশনটি দেখুন: https://developer.apple.com/videos/play/wwdc2017/220/

এখানে চিত্র বর্ণনা লিখুন


2
@ শোভাকার তিওয়ারি কেন? আইওএস 11 আনুষ্ঠানিক প্রকাশে কোনও পরিবর্তন ঘটে?
জ্যাকি

আপনি কেবল iOS 11 এবং তত বেশি সমর্থন করে যদি আপনি পূর্ববর্তী সংস্করণগুলি সমর্থন করতে চান তবে পৃষ্ঠা লোড হওয়ার আগে জাভাস্ক্রিপ্ট ব্যবহার করুন Best
পাশাএন

এটি আমার পক্ষে কাজ করে, কখনও কখনও সেটকুকি পদ্ধতিটি তার সমাপ্তি হ্যান্ডলারটি চালায় না, যার অর্থ কখনও কখনও আমার ওয়েব পৃষ্ঠাটি লোড হয় না - কেবল ডিভাইসে ঘটে, তৃতীয় / চতুর্থ / 5 তমবার বন্ধ হয়ে যাওয়া এবং পুনরায় খোলা হয় ওয়েবভিউ, এবং এটি একবার হওয়ার পরে, আমি অ্যাপটি রিসেট না হওয়া পর্যন্ত এটি ঘটতে থাকবে - কেউ কি এটিকে চালিত করে না?
বিনয়া কোয়াটজ

5

এই উত্তরটি পোস্ট করার পিছনে কারণটি হ'ল আমি অনেকগুলি সমাধানের চেষ্টা করেছি তবে কেউই সঠিকভাবে কাজ করে না, প্রথমবার কুকি সেট করতে হবে এমন ফলাফলের বেশিরভাগ উত্তর কাজ করে না, এবং ফলাফল কুকি প্রথমবার সিঙ্ক না করে, এই সমাধানটি ব্যবহার করুন এটি উভয়ের জন্যই কার্যকর আইওএস> = 11.0 <= আইওএস 11 8.0 অবধি, প্রথমবার কুকি সিঙ্কের সাথেও কাজ করে।

আইওএস> = 11.0 - সুইফট 4.2

HTTP কুকিজ পান এবং wkwebview কুকি স্টোরকে এভাবে সেট করুন , আপনার অনুরোধটি ডাব্লুউইউউবিউতে লোড করা খুব জটিল বিষয় , কুকিজ সম্পূর্ণরূপে সেট হওয়ার সময় লোডিংয়ের জন্য অনুরোধ পাঠাতে হবে, আমি এখানে লিখেছি যে ফাংশনটি এখানে রয়েছে।

এর মাধ্যমে কল করুন ফাংশন অবসান সম্পূর্ণতে আপনি লোড WebView কল। এফওয়াইআই এই ফাংশনটি কেবল আইওএস> = 11.0 হ্যান্ডেল করে

self.WwebView.syncCookies {
    if let request = self.request {
       self.WwebView.load(request)
    }
}

সিঙ্ককুকিজ ফাংশনটির জন্য এখানে বাস্তবায়ন দেওয়া হচ্ছে ।

func syncCookies(completion:@escaping ()->Void) {

if #available(iOS 11.0, *) {

      if let yourCookie = "HERE_YOUR_HTTP_COOKIE_OBJECT" {
        self.configuration.websiteDataStore.httpCookieStore.setCookie(yourCookie, completionHandler: {
              completion()
        })
     }
  } else {
  //Falback just sent 
  completion()
}
}

আইওএস 8 এর জন্য আইওএস 11 পর্যন্ত

আপনাকে ডাব্লুউইউএসএসর স্ক্রিপ্ট ব্যবহারের মাধ্যমে দু'বারের কুকিজ সেট করতে আপনার অতিরিক্ত কিছু জিনিস সেটআপ করতে হবে এবং অনুরোধে কুকিজ যুক্ত করতে ভুলবেন না, অন্যথায় আপনার কুকিটি প্রথমবার সিঙ্ক হয় না এবং আপনি পৃষ্ঠাটি প্রথমবার ঠিকমতো লোড না করে দেখবেন। এটি হ্যাক যা আমি iOS 8.0 এর জন্য কুকিজ সমর্থন করতে দেখেছি

আপনার আগে Wkwebview অবজেক্ট তৈরি।

func setUpWebView() {

    let userController: WKUserContentController = WKUserContentController.init()

    if IOSVersion.SYSTEM_VERSION_LESS_THAN(version: "11.0") {
        if let cookies = HTTPCookieStorage.shared.cookies {
            if let script = getJSCookiesString(for: cookies) {
                cookieScript = WKUserScript(source: script, injectionTime: .atDocumentStart, forMainFrameOnly: false)
                userController.addUserScript(cookieScript!)
            }
        }
    }

    let webConfiguration = WKWebViewConfiguration()
    webConfiguration.processPool = BaseWebViewController.processPool


    webConfiguration.userContentController = userController


    let customFrame = CGRect.init(origin: CGPoint.zero, size: CGSize.init(width: 0.0, height: self.webContainerView.frame.size.height))
    self.WwebView = WKWebView (frame: customFrame, configuration: webConfiguration)
    self.WwebView.translatesAutoresizingMaskIntoConstraints = false
    self.webContainerView.addSubview(self.WwebView)
    self.WwebView.uiDelegate = self
    self.WwebView.navigationDelegate = self
    self.WwebView.allowsBackForwardNavigationGestures = true // A Boolean value indicating whether horizontal swipe gestures will trigger back-forward list navigations
    self.WwebView.addObserver(self, forKeyPath: #keyPath(WKWebView.estimatedProgress), options: .new, context: nil)


 self.view.addConstraint(NSLayoutConstraint(item: WwebView, attribute: .trailing, relatedBy: .equal, toItem: self.webContainerView, attribute: .trailing, multiplier: 1, constant: 0))
    self.view.addConstraint(NSLayoutConstraint(item: WwebView, attribute: .leading, relatedBy: .equal, toItem: self.webContainerView, attribute: .leading, multiplier: 1, constant: 0))
    self.view.addConstraint(NSLayoutConstraint(item: WwebView, attribute: .top, relatedBy: .equal, toItem: self.webContainerView, attribute: .top, multiplier: 1, constant: 0))
    self.view.addConstraint(NSLayoutConstraint(item: WwebView, attribute: .bottom, relatedBy: .equal, toItem: self.webContainerView, attribute: .bottom, multiplier: 1, constant: 0))


}

জেএসসি কুকিস্ট্রিং এই ফাংশনটিতে ফোকাস করুন

 public func getJSCookiesString(for cookies: [HTTPCookie]) -> String? {

    var result = ""
    let dateFormatter = DateFormatter()
    dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
    dateFormatter.dateFormat = "EEE, d MMM yyyy HH:mm:ss zzz"

    for cookie in cookies {
        if cookie.name == "yout_cookie_name_want_to_sync" {
            result += "document.cookie='\(cookie.name)=\(cookie.value); domain=\(cookie.domain); path=\(cookie.path); "
            if let date = cookie.expiresDate {
                result += "expires=\(dateFormatter.string(from: date)); "
            }
            if (cookie.isSecure) {
                result += "secure; "
            }
            result += "'; "
        }

    }

    return result
}

এখানে অন্য পদক্ষেপ উইকিউসারস্ক্রিপ্ট তত্ক্ষণাত কুকিগুলি সিঙ্ক করে না, সেখানে কুকির সাথে প্রথমবারের পৃষ্ঠাটি লোড করার জন্য প্রচুর হেক হ'ল ওয়েবভিউ পুনরায় লোড করা যদি এটি প্রক্রিয়াটি শেষ করে তবে আমি এটি ব্যবহার করার পরামর্শ দিই না, এটি ব্যবহারকারীর দৃষ্টিকোণের জন্য ভাল নয় one , হ্যাক আপনি যখনই অনুরোধ শিরোনামে অনুরোধ কুকিজ লোড করতে প্রস্তুত হন তেমনি এইভাবে, আইওএস সংস্করণ চেক যুক্ত করতে ভুলবেন না। লোড অনুরোধ আগে এই ফাংশন কল।

request?.addCookies()

আমি URLRequest জন্য এক্সটেনশন লিখেছি

extension URLRequest {

internal mutating func addCookies() {
    //"appCode=anAuY28ucmFrdXRlbi5yZXdhcmQuaW9zLXpOQlRTRmNiejNHSzR0S0xuMGFRb0NjbUg4Ql9JVWJH;rpga=kW69IPVSYZTo0JkZBicUnFxC1g5FtoHwdln59Z5RNXgJoMToSBW4xAMqtf0YDfto;rewardadid=D9F8CE68-CF18-4EE6-A076-CC951A4301F6;rewardheader=true"
    var cookiesStr: String = ""

    if IOSVersion.SYSTEM_VERSION_LESS_THAN(version: "11.0") {
        let mutableRequest = ((self as NSURLRequest).mutableCopy() as? NSMutableURLRequest)!
        if let yourCookie = "YOUR_HTTP_COOKIE_OBJECT" {
            // if have more than one cookies dont forget to add ";" at end
            cookiesStr += yourCookie.name + "=" + yourCookie.value + ";"

            mutableRequest.setValue(cookiesStr, forHTTPHeaderField: "Cookie")
            self = mutableRequest as URLRequest

        }
    }

  }
}

এখন আপনি আইওএস> 8 পরীক্ষার জন্য প্রস্তুত


2

সম্ভবত সমাধানটি খুঁজে বার করুন যা সম্ভবত আপনার জন্য বাক্সের বাইরে কাজ করবে। মূলত এটি সুইফট 4 @ ব্যবহারকারী 3589213 এর উত্তরের জন্য সংশোধিত এবং আপডেট হয়েছে ।

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
    let headerKeys = navigationAction.request.allHTTPHeaderFields?.keys
    let hasCookies = headerKeys?.contains("Cookie") ?? false

    if hasCookies {
        decisionHandler(.allow)
    } else {
        let cookies = HTTPCookie.requestHeaderFields(with: HTTPCookieStorage.shared.cookies ?? [])

        var headers = navigationAction.request.allHTTPHeaderFields ?? [:]
        headers += cookies

        var req = navigationAction.request
        req.allHTTPHeaderFields = headers

        webView.load(req)

        decisionHandler(.cancel)
    }
}

1

আমি উপরের সমস্ত উত্তর চেষ্টা করেছি কিন্তু সেগুলির কোনওটিই কাজ করে না। অনেক চেষ্টার পরে অবশেষে আমি ডব্লুউইউবভিউ কুকি সেট করার একটি নির্ভরযোগ্য উপায় খুঁজে পেয়েছি।

প্রথমে আপনাকে ডব্লু কেপ্রসেসপুলের একটি উদাহরণ তৈরি করতে হবে এবং ডাব্লুউইউবিউভিউ কনফিগারেশনে সেট করতে হবে যা নিজেই ডাব্লুউইউবভিউকে সূচনা করার জন্য ব্যবহার করতে হবে:

    private lazy var mainWebView: WKWebView = {
        let webConfiguration = WKWebViewConfiguration()
        webConfiguration.processPool = WKProcessPool()
        let webView = WKWebView(frame: .zero, configuration: webConfiguration)
        webView.navigationDelegate = self
        return webView
    }()

ডাব্লু কেপ্রসেসপুল সেট করা এখানে সর্বাধিক গুরুত্বপূর্ণ পদক্ষেপ। ডাব্লুউইউভিউভিউ প্রক্রিয়া বিচ্ছিন্নকরণের ব্যবহার করে - যার অর্থ এটি আপনার অ্যাপ্লিকেশন প্রক্রিয়ার চেয়ে আলাদা প্রক্রিয়াতে চলে। এটি কখনও কখনও দ্বন্দ্ব সৃষ্টি করতে পারে এবং আপনার কুকিকে ডাব্লুউইউ ভিউভিউয়ের সাথে সঠিকভাবে সিঙ্ক করা থেকে আটকাতে পারে।

এখন আসুন WKProcessPool এর সংজ্ঞাটি দেখুন

একটি ওয়েব দৃশ্যের সাথে সম্পর্কিত প্রক্রিয়া পুলটি তার ওয়েব ভিউ কনফিগারেশন দ্বারা নির্দিষ্ট করা হয়। বাস্তবায়ন-সংজ্ঞায়িত প্রক্রিয়া সীমা না হওয়া পর্যন্ত প্রতিটি ওয়েব দর্শনকে তার নিজস্ব ওয়েব সামগ্রী প্রক্রিয়া দেওয়া হয়; এর পরে, একই প্রক্রিয়া পুলের সাথে ওয়েব দর্শনগুলি ওয়েব সামগ্রীর প্রক্রিয়াগুলি ভাগ করে নেবে।

আপনি যদি পরের অনুরোধগুলির জন্য একই ডাব্লুউইউউবভিউটি ব্যবহার করার পরিকল্পনা করেন তবে সর্বশেষ বাক্যে মনোযোগ দিন

একই প্রসেস পুলের সাথে ওয়েব দর্শনগুলি ওয়েব সামগ্রীর প্রক্রিয়াগুলি ভাগ করে নেবে

আমার অর্থ হ'ল আপনি যদি প্রতিবার একই ডোমেনের জন্য ডাব্লুউইউবিউভিউ কনফিগার করেন আপনি ডাব্লুপি প্রসেসপুলের একই উদাহরণটি ব্যবহার না করেন (সম্ভবত আপনার কাছে একটি ভিসি এ রয়েছে যাতে একটি ডব্লিউবিউ ভিউ রয়েছে এবং আপনি বিভিন্ন জায়গায় ভিসি এ এর ​​বিভিন্ন উদাহরণ তৈরি করতে চান ), সংঘাতের সেটিং কুকিজ থাকতে পারে। সমস্যা সমাধানের জন্য, ডাব্লু বি লোড করে এমন কোনও ডব্লিউকেউবিউ ভিউর জন্য ডাব্লুকেপ্রসেসপুলের প্রথম তৈরির পরে, আমি এটি একটি সিঙ্গলটনে সংরক্ষণ করি এবং প্রতিবারই আমি ডব্লুকেউভিউ ভিউ তৈরি করি যা একই ডোমেন বি লোড করে s

private lazy var mainWebView: WKWebView = {
    let webConfiguration = WKWebViewConfiguration()
    if Enviroment.shared.processPool == nil {
        Enviroment.shared.processPool = WKProcessPool()
    }
    webConfiguration.processPool = Enviroment.shared.processPool!
    webConfiguration.processPool = WKProcessPool()
    let webView = WKWebView(frame: .zero, configuration: webConfiguration)
    webView.navigationDelegate = self
    return webView
}()

আরম্ভের প্রক্রিয়া পরে, আপনি একটি URLRequest লোড করতে পারেন সমাপ্তির ব্লক ভিতরে এর httpCookieStore.setCookie। এখানে আপনাকে কুকিকে অনুরোধ শিরোনামের সাথে সংযুক্ত করতে হবে অন্যথায় এটি কাজ করবে না।

পি / এস: আমি উপরের চমত্কার উত্তর থেকে এক্সটেনশানটি চুরি করেছি ড্যান লোয়েহের্জেস

mainWebView.configuration.websiteDataStore.httpCookieStore.setCookie(your_cookie) {
        self.mainWebView.load(your_request, with: [your_cookie])
}

extension WKWebView {
   func load(_ request: URLRequest, with cookies: [HTTPCookie]) {
      var request = request
      let headers = HTTPCookie.requestHeaderFields(with: cookies)
      for (name, value) in headers {
         request.addValue(value, forHTTPHeaderField: name)
      }        
      load(request)
   }
}

1

আমার সংস্করণ nteiss এর উত্তর। পরীক্ষিত iOS 11, 12, 13। দেখে মনে হচ্ছে আপনাকে আর ব্যবহার করতে DispatchGroupহবে iOS 13না।

আমি অ স্ট্যাটিক ফাংশন ব্যবহার includeCustomCookiesউপর WKWebViewConfiguration, যাতে আমি আপডেট করতে পারেন cookiesপ্রত্যেক সময় আমি নতুন তৈরি WKWebViewConfiguration

extension WKWebViewConfiguration {
    func includeCustomCookies(cookies: [HTTPCookie], completion: @escaping  () -> Void) {
        let dataStore = WKWebsiteDataStore.nonPersistent()
        let waitGroup = DispatchGroup()

        for cookie in cookies {
            waitGroup.enter()
            dataStore.httpCookieStore.setCookie(cookie) { waitGroup.leave() }
        }

        waitGroup.notify(queue: DispatchQueue.main) {
            self.websiteDataStore = dataStore
            completion()
        }
    }
}

তারপরে আমি এটি এর মতো ব্যবহার করব:

let customUserAgent: String = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1.1 Safari/605.1.15"

let customCookies: [HTTPCookie] = {
    let cookie1 = HTTPCookie(properties: [
        .domain: "yourdomain.com",
        .path: "/",
        .name: "auth_token",
        .value: APIManager.authToken
    ])!

    let cookie2 = HTTPCookie(properties: [
        .domain: "yourdomain.com",
        .path: "/",
        .name: "i18next",
        .value: "ru"
    ])!

    return [cookie1, cookie2]
}()

override func viewDidLoad() {
    super.viewDidLoad()

    activityIndicatorView.startAnimating()

    let webConfiguration = WKWebViewConfiguration()
    webConfiguration.includeCustomCookies(cookies: customCookies, completion: { [weak self] in
        guard let strongSelf = self else { return }
        strongSelf.webView = WKWebView(frame: strongSelf.view.bounds, configuration: webConfiguration)
        strongSelf.webView.customUserAgent = strongSelf.customUserAgent
        strongSelf.webView.navigationDelegate = strongSelf
        strongSelf.webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        strongSelf.view.addSubview(strongSelf.webView)
        strongSelf.view.bringSubviewToFront(strongSelf.activityIndicatorView)
        strongSelf.webView.load(strongSelf.request)
    })
}

0

এক্সএইচআর অনুরোধগুলির জন্য আরও ভাল ফিক্সটি এখানে দেখানো হয়েছে

সুইফট 4 সংস্করণ:

func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Swift.Void) {
    guard
        let response = navigationResponse.response as? HTTPURLResponse,
        let url = navigationResponse.response.url
    else {
        decisionHandler(.cancel)
        return
    }

    if let headerFields = response.allHeaderFields as? [String: String] {
        let cookies = HTTPCookie.cookies(withResponseHeaderFields: headerFields, for: url)
        cookies.forEach { (cookie) in
            HTTPCookieStorage.shared.setCookie(cookie)
        }
    }

    decisionHandler(.allow)
}

0

যদি কেউ আলামোফায়ার ব্যবহার করে থাকে তবে এটি আরও ভাল সমাধান।

  let cookies = Alamofire.SessionManager.default.session.configuration.httpCookieStorage?.cookies(for: URL(string: BASE_URL)!)
  for (cookie) in cookies ?? [] {
      webView.configuration.websiteDataStore.httpCookieStore.setCookie(cookie)
  }

0

এটি আমার জন্য কাজ করে: সেটকিউজির পরে, ফেচডাটারেকর্ডস যুক্ত করুন

   let cookiesSet = NetworkProvider.getCookies(forKey : 
    PaywallProvider.COOKIES_KEY, completionHandler: nil)
                let dispatchGroup = DispatchGroup()
                for (cookie) in cookiesSet {
                    if #available(iOS 11.0, *) {
                        dispatchGroup.enter()
                        self.webView.configuration.websiteDataStore.httpCookieStore.setCookie(cookie){
                            dispatchGroup.leave()
                            print ("cookie added: \(cookie.description)")
                            }
                        } else {
                                            // TODO Handle ios 10 Fallback on earlier versions
                        }
                    }
                    dispatchGroup.notify(queue: .main, execute: {


    self.webView.configuration.websiteDataStore.fetchDataRecords(ofTypes: 
    WKWebsiteDataStore.allWebsiteDataTypes()) { records in
                            records.forEach { record in

                                print("[WebCacheCleaner] Record \(record)")
                            }
                            self.webView.load(URLRequest(url: 
    self.dataController.premiumArticleURL , 
    cachePolicy:NSURLRequest.CachePolicy.reloadIgnoringLocalAndRemoteCacheData,
                                                         timeoutInterval: 10.0))
                        }

                    })
                }

0

গুণিত কুকি আইটেম যুক্ত করার সময়, আপনি এটি এর মতো এটি করতে পারেন: ( pathএবং domainপ্রতিটি আইটেমের জন্য প্রয়োজন)

NSString *cookie = [NSString stringWithFormat:@"document.cookie = 'p1=%@;path=/;domain=your.domain;';document.cookie = 'p2=%@;path=/;domain=your.domain;';document.cookie = 'p3=%@;path=/;domain=your.domain;';", p1_string, p2_string, p3_string];

WKUserScript *cookieScript = [[WKUserScript alloc]
            initWithSource:cookie
            injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];

[userContentController addUserScript:cookieScript];

অন্যথায়, শুধুমাত্র প্রথম কুকি আইটেম সেট করা হবে।


0

ইউআইউইউবভিউ থেকে HTTPCookieStorage এর অনুরূপ আচরণ পেতে আপনি WKWebsiteDataStore ব্যবহার করতে পারেন।

let dataStore = WKWebsiteDataStore.default()
let cookies = HTTPCookieStorage.shared.cookies ?? [HTTPCookie]()
cookies.forEach({
    dataStore.httpCookieStore.setCookie($0, completionHandler: nil)
})

0

কোডের নীচে আমার প্রজেক্ট সুইফট 5 এ ভাল কাজ করছে। নীচে WKWebView দ্বারা ইউআরএল লোড চেষ্টা করুন:

    private func loadURL(urlString: String) {
        let url = URL(string: urlString)
        guard let urlToLoad = url else { fatalError("Cannot find any URL") }

        // Cookies configuration
        var urlRequest = URLRequest(url: urlToLoad)
        if let cookies = HTTPCookieStorage.shared.cookies(for: urlToLoad) {
            let headers = HTTPCookie.requestHeaderFields(with: cookies)
            for header in headers { urlRequest.addValue(header.value, forHTTPHeaderField: header.key) }
        }

        webview.load(urlRequest)
    }

0

আইওএস 9 বা তারপরে কুকিজ এবং ডব্লিউকেউইউভিউয়ের সাথে পরিচালনা করার জন্য এটি আমার সমাধান।

import WebKit

extension WebView {

    enum LayoutMode {
        case fillContainer
    }

    func autoLayout(_ view: UIView?, mode: WebView.LayoutMode = .fillContainer) {
        guard let view = view else { return }
        self.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(self)

        switch mode {
        case .fillContainer:
                NSLayoutConstraint.activate([
                self.topAnchor.constraint(equalTo: view.topAnchor),
                self.leadingAnchor.constraint(equalTo: view.leadingAnchor),
                self.trailingAnchor.constraint(equalTo: view.trailingAnchor),
                self.bottomAnchor.constraint(equalTo: view.bottomAnchor)
            ])
        }
    }

}

class WebView : WKWebView {

    var request : URLRequest?

    func load(url: URL, useSharedCookies: Bool = false) {
        if useSharedCookies, let cookies = HTTPCookieStorage.shared.cookies(for: url) {
            self.load(url: url, withCookies: cookies)
        } else {
            self.load(URLRequest(url: url))
        }
    }

    func load(url: URL, withCookies cookies: [HTTPCookie]) {
        self.request = URLRequest(url: url)
        let headers = HTTPCookie.requestHeaderFields(with: cookies)
        self.request?.allHTTPHeaderFields = headers
        self.load(request!)
    }

}

0

আমি যে ভুলটি করছিলাম তা হ'ল আমি সম্পূর্ণ ইউআরএলটি ডোমেন বৈশিষ্ট্যে পাস করছিলাম, এটি কেবলমাত্র ডোমেন নাম হওয়া উচিত name

let cookie = HTTPCookie(properties: [
.domain: "example.com",
.path: "/",
.name: "MyCookieName",
.value: "MyCookieValue",
.secure: "TRUE",
])! 

webView.configuration.websiteDataStore.httpCookieStore.setCookie(cookie)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.