Getting all cookies from WKWebView Getting all cookies from WKWebView ios ios

Getting all cookies from WKWebView


Cookies used (created) by the WKWebView are actually correctly stored in the NSHTTPCookieStorage.sharedHTTPCookieStorage().

The problem is that the WKWebView does not write back the cookies immediately. I think it does this on its own schedule. For example when a WKWebView is closed or maybe periodically.

So eventually they do end up in there, but when is unpredictable.

You may be able to force a 'sync' to the shared NSHTTPCookieStorage by closing your WKWebView. Please let us know if this works.

Update: I just remembered that in Firefox for iOS we force the WKWebView to flush its internal data, including cookies, by replacing its WKProcessPool with a new one. There is no official API, but I am pretty sure that is the most reliable workaround right now.


Details

  • Xcode 9.2, Swift 4
  • Xcode 10.2 (10E125), Swift 5

Solution

extension WKWebView {    private var httpCookieStore: WKHTTPCookieStore  { return WKWebsiteDataStore.default().httpCookieStore }    func getCookies(for domain: String? = nil, completion: @escaping ([String : Any])->())  {        var cookieDict = [String : AnyObject]()        httpCookieStore.getAllCookies { cookies in            for cookie in cookies {                if let domain = domain {                    if cookie.domain.contains(domain) {                        cookieDict[cookie.name] = cookie.properties as AnyObject?                    }                } else {                    cookieDict[cookie.name] = cookie.properties as AnyObject?                }            }            completion(cookieDict)        }    }}

Usage

// get cookies for domainwebView.getCookies(for: url.host) { data in      print("=========================================")      print("\(url.absoluteString)")      print(data)}// get all cookieswebView.getCookies() { data in      print("=========================================")      print("\(url.absoluteString)")      print(data)}

Full sample

Info.plist

add in your Info.plist transport security setting

 <key>NSAppTransportSecurity</key> <dict>    <key>NSAllowsArbitraryLoads</key>    <true/> </dict>

Code

  1. Do not forget to add the solution code here
  2. ViewController has embed view controller
import UIKitimport WebKitclass ViewController: UIViewController {    private lazy var url = URL(string: "https://google.com")!    private weak var webView: WKWebView?    func initWebView(configuration: WKWebViewConfiguration) {        if webView != nil { return }        let webView = WKWebView(frame: UIScreen.main.bounds, configuration: configuration)        webView.navigationDelegate = self        webView.uiDelegate = self        view.addSubview(webView)        self.webView = webView    }    override func viewWillAppear(_ animated: Bool) {        super.viewWillAppear(animated)        if webView == nil { initWebView(configuration: WKWebViewConfiguration()) }        webView?.load(url: url)    }}extension ViewController: WKNavigationDelegate {    func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {        decisionHandler(.allow)    }    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {        if let url = webView.url {            webView.getCookies(for: url.host) { data in                print("=========================================")                print("\(url.absoluteString)")                print(data)            }        }    }}extension ViewController: WKUIDelegate {    func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {        // push new screen to the navigation controller when need to open url in another "tab"        if let url = navigationAction.request.url, navigationAction.targetFrame == nil {            let viewController = ViewController()            viewController.initWebView(configuration: configuration)            viewController.url = url            DispatchQueue.main.async { [weak self] in                self?.navigationController?.pushViewController(viewController, animated: true)            }            return viewController.webView        }        return nil    }}extension WKWebView {    func load(urlString: String) {        if let url = URL(string: urlString) { load(url: url) }    }    func load(url: URL) { load(URLRequest(url: url)) }}

enter image description here