Solución:
Cookies utilizadas (creadas) por el WKWebView
están almacenados correctamente en el NSHTTPCookieStorage.sharedHTTPCookieStorage()
.
El problema es que el WKWebView
no escribe las cookies inmediatamente. Creo que hace esto en su propio horario. Por ejemplo, cuando un WKWebView
está cerrado o tal vez periódicamente.
Así que eventualmente terminan ahí, pero cuando es impredecible.
Es posible que pueda forzar una “sincronización” con el contenido compartido. NSHTTPCookieStorage
cerrando tu WKWebView
. Háganos saber si esto funciona.
Actualizar: Acabo de recordar que en Firefox para iOS forzamos la WKWebView
para vaciar sus datos internos, incluidas las cookies, reemplazando su WKProcessPool
con uno nuevo. No hay una API oficial, pero estoy bastante seguro de que es la solución más confiable en este momento.
Finalmente, httpCookieStore
por WKWebsiteDataStore
aterrizó en iOS 11.
https://developer.apple.com/documentation/webkit/wkwebsitedatastore?changes=latest_minor
Detalles
- Xcode 9.2, Swift 4
- Xcode 10.2 (10E125), Swift 5
Solución
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)
}
}
}
Uso
// get cookies for domain
webView.getCookies(for: url.host) { data in
print("=========================================")
print("(url.absoluteString)")
print(data)
}
// get all cookies
webView.getCookies() { data in
print("=========================================")
print("(url.absoluteString)")
print(data)
}
Muestra completa
Info.plist
agregue su configuración de seguridad de transporte Info.plist
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
Código
- No olvides agregue el código de la solución aquí
- ViewController tiene un controlador de vista incrustado
import UIKit
import WebKit
class 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)) }
}