iOS Swift中如何监听WKWebView获取指定页面的Cookie
Hey fellow iOS dev! Let's figure out how to fix your WKWebView cookie issue. I see you're having trouble grabbing the login cookie at the right time, so let's break this down step by step.
First, let's spot the key issues in your current code
- You're using the wrong cookie storage:
HTTPCookieStorage.sharedis for UIWebView and shared URL sessions, but WKWebView stores its cookies in its ownWKHTTPCookieStore(part of itsWKWebsiteDataStore). That's why you might not be seeing the login cookie there. - URL/progress listening isn't reliable: Waiting for
estimatedProgressto hit 1.0 doesn't guarantee the login cookie has been set yet—page load completion and cookie sync can happen asynchronously.
Solution 1: Use WKNavigationDelegate to detect login completion
The most straightforward way to know when login is done is to watch for the navigation to your app's home page (the page after login). Here's how to implement this:
First, set the navigation delegate for your WKWebView in viewDidLoad:
override func viewDidLoad() { super.viewDidLoad() webView.navigationDelegate = self // ... rest of your setup code }
Then implement the delegate methods to detect login success and grab the cookie:
extension YourViewController: WKNavigationDelegate { // Triggered when a page finishes loading func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { guard let currentURL = webView.url else { return } // Replace "homeURL" with your actual post-login homepage URL if currentURL.absoluteString == homeURL { // Login is done—now fetch the cookie fetchLoginCookie(from: webView) } } // Optional: Detect the navigation to home page before it loads func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { if let targetURL = navigationAction.request.url, targetURL.absoluteString == homeURL { print("Login successful! About to navigate to home page.") } decisionHandler(.allow) } // Helper to fetch and use the login cookie private func fetchLoginCookie(from webView: WKWebView) { let cookieStore = webView.configuration.websiteDataStore.httpCookieStore cookieStore.getAllCookies { cookies in // Filter cookies to find the one you need (e.g., by name or domain) let loginCookie = cookies.first { cookie in cookie.name == "your-login-cookie-name" // Replace with your cookie's name // OR filter by domain: cookie.domain == "your-app-domain.com" } guard let cookie = loginCookie else { print("Login cookie not found!") return } // Now use this cookie to make your HTTP request self.makeRequestWithCookie(cookie: cookie) } } // Example: Make an HTTP request with the cookie private func makeRequestWithCookie(cookie: HTTPCookie) { guard let apiURL = URL(string: "your-api-endpoint-url") else { return } var request = URLRequest(url: apiURL) // Convert the cookie to request header fields let cookieHeaders = HTTPCookie.requestHeaderFields(with: [cookie]) request.allHTTPHeaderFields?.merge(cookieHeaders) { $1 } // Override existing headers if needed // Send the request URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Request failed: \(error.localizedDescription)") return } // Handle your response data here... if let data = data { print("Received data: \(String(data: data, encoding: .utf8) ?? "")") } }.resume() } }
Solution 2: Listen for cookie changes directly
If you want to catch the cookie as soon as it's set (even before the home page loads), you can observe changes to the WKHTTPCookieStore:
Add this observer in viewDidLoad:
override func viewDidLoad() { super.viewDidLoad() let cookieStore = webView.configuration.websiteDataStore.httpCookieStore cookieStore.addObserver(self, forKeyPath: "cookies", options: .new, context: nil) }
Then implement the observer method:
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { guard keyPath == "cookies", let cookieStore = object as? WKHTTPCookieStore else { super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) return } cookieStore.getAllCookies { cookies in let loginCookie = cookies.first { $0.name == "your-login-cookie-name" } if let cookie = loginCookie { print("Found login cookie!") self.makeRequestWithCookie(cookie: cookie) // Stop observing once we get the cookie to avoid redundant calls cookieStore.removeObserver(self, forKeyPath: "cookies") } } }
Key Takeaways
- Always use
WKWebView.configuration.websiteDataStore.httpCookieStoreto access WKWebView's cookies—forgetHTTPCookieStorage.sharedfor WKWebView unless you explicitly enabled cookie sharing. - Use
WKNavigationDelegateto reliably detect when the user has logged in (via the home page URL). - If you need the cookie immediately after it's set, observe the
cookieskey path onWKHTTPCookieStore.
内容的提问来源于stack exchange,提问作者Razon

