Eugeny
Eugeny

Reputation: 308

How to use same cookie on different WKWebViews

i need to use same configuration (cookie) on the second WebView after the user is authorized on first WebView. On simulator it's work well, but on device is not stable.

class auth: UIViewController, WKNavigationDelegate, UIWebViewDelegate {
private var webView: WKWebView = WKWebView()
    override func viewDidLoad() {
        super.viewDidLoad()
        webView.navigationDelegate = self
        loadPage(urlString: link)
    }
    private func loadPage(urlString: String) {
        if let encodedURL = urlString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed),
            let url = URL(string: encodedURL) {
            let request = URLRequest(url: url)
            webView.refreshCookies()
            webView.load(request)
        }
    }
}

extension WKWebView {
    func refreshCookies() {
        self.configuration.websiteDataStore = WKWebsiteDataStore.default()
    }
}

Upvotes: 0

Views: 2283

Answers (3)

Brittany
Brittany

Reputation: 276

Instead of keeping a global cookie variable or saving to plist as mentioned above, you can set cookies in the shared HTTPCookieStorage.

To store:

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {

    let request = navigationAction.request
    let url = request.url

    webView.configuration.websiteDataStore.httpCookieStore.getAllCookies { (cookies) in
         HTTPCookieStorage.shared.setCookies(cookies, for: url, mainDocumentURL: nil)
    }

    decisionHandler(.allow)
    return
}

And to retrieve and set (in a different WebView instance):

let frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height) 
let config = WKWebViewConfiguration()
let cookies = HTTPCookieStorage.shared.cookies ?? []
for cookie in cookies {
    config.websiteDataStore.httpCookieStore.setCookie(cookie, completionHandler: nil)
}

let webView2 = WKWebView(frame: frame, configuration: config)

Hope this is helpful

Upvotes: 1

Muhammad Shauket
Muhammad Shauket

Reputation: 2778

Every ** WKWebView** has it's own cookie space that cookie space is saved in WKProcessPool just make process pool object global and assign to every webview object, hope so this will work in your case.

    static let processPool = WKProcessPool()

And set your WKWebView instance every time with this process pool, other way is whenever you creating wkwebview and load implement this function.

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

    if #available(iOS 11.0, *) {
        self.webView.httpCookieStore.getAllCookies { (cookies) in
            cookies.forEach({ (cookie) in
                if cookie.name == Constant.appCodeCookie || cookie.name == Constant.rpgaCookieName || cookie.name == Constant.headerCookie , cookie.name == Constant.adIdCookie {
                    HTTPCookieStorage.shared.setCookie(cookie)
                }
            })
        }

    } else {
        // Fallback version
        if  let allHttpHeaders = response.allHeaderFields as? [String: String] {
            let cookies = HTTPCookie.cookies(withResponseHeaderFields: allHttpHeaders, for: responseUrl)
            for cookie in cookies {
                HTTPCookieStorage.shared.setCookie(cookie)
            }
        }
    }


    decisionHandler(.allow)
}

Every time you make instance of wkwebview just get all cookies from httpcookiestorage and set in wkwebview user script for further you can check my answer here also. Can I set the cookies to be used by a WKWebView?

Upvotes: 1

hafiz8009
hafiz8009

Reputation: 1

You need to set cookie for each wkwebview, So keep the cookie value as global variable or save it in plist.

Upvotes: 0

Related Questions