2

我有下面的代码将 cookie 从 general 复制HTTPCookieStorage到我的 webview 的 cookie 存储中。复制所有 cookie 后,我加载 webview

    let webView = WKWebView(frame: containerView.bounds, configuration: WKWebViewConfiguration())
    webView.navigationDelegate = navigationDelegate
    containerView.addAndFillSubview(webView)
    guard let sharedCookies = HTTPCookieStorage.shared.cookies else {
        return
    }

    // For each cookie in the common store, set it in the WKWebView's store.
    for sharedCookie in sharedCookies {
        // Add a block to the dispatch group every time a cookie begins to be set in the WKWebView's store.
        wkSetCookieDispatchGroup.enter() 
        webView.configuration.websiteDataStore.httpCookieStore.setCookie(sharedCookie) {
           // Release a block from the dispatch group every time a cookie is successfully set in the WKWebView's store.
           wkSetCookieDispatchGroup.leave()
        }
    }

    // Wait for all the cookies to be successfully set (all blocks in the wkSetCookieDispatchGroup to be released)
    wkSetCookieDispatchGroup.notify(queue: .main) {
       // Load url in webView
    }

这段代码第一次运行时就可以工作——所有的 cookie 都被设置,setCookie完成处理程序被调用并且调度组被通知。

但是,在关闭此 Web 视图并打开它setCookie的 n 次运行(通常是 3 或 4 次)之后,完成处理程序会停止返回,通常是无限期地返回。有一些竞争条件正在发生,因为如果我设置断点并在每次 web 视图打开时点击它们,这个问题就永远不会发生。发生一次后,设置断点有时会使其重新开始工作,有时什么也不做。

注意:这只发生在设备上。在模拟器上,这永远不会发生。

没有关于setCookiecompletionHandler 何时应该返回或不返回的文档,而且这是一个竞争条件,当你有断点时通常不会发生这种情况,这使得调试变得异常困难。

有没有其他人经历过这个?有什么建议吗?我尝试在几个地方明确设置 WKProcessPool,但没有成功。我尝试在创建配置之前和之后创建 Web 视图。我已经尝试了很多东西,但仍然失败了

4

2 回答 2

0

不确定这是否符合您的要求,但我遇到了同样的问题,发现我创建的每个 WKWebViewConfiguration 都使用相同的 cookie 存储,以便与不同的 WKWebView 一起使用。

因为我需要为我将使用的任何 wk webview 实例创建相同的 cookie,所以我最终做的是创建一个单例 WKWebViewConfiguration,它添加一次所需的 cookie,设置一个 WKProcessPool,然后返回一个副本。

我需要的每个不同的 wk webview 都会在副本上设置其自定义配置,但不必与 cookie 存储交互。

遇到同样的问题后,似乎对我有用。

于 2018-04-13T16:02:23.953 回答
0

Apple Transport Security尝试通过在 info.plist 中添加密钥Allow Arbitrary Loads来关闭YES. (只是为了解决问题,即使它解决了问题,也不鼓励将其作为解决方案)

根据我的经验,setCookie如果您的应用程序向 Apple Transport Security (ATS) 确认并且您尝试调用设置非安全cookie,则不会调用完成处理程序块。

PS:从 iOS 12.2 开始,这似乎是 WebKit 的一个未记录的事实

以下是我个人在我们的 iOS 应用程序中注意到的细节 -

我们在符合 ATS 的应用程序中有以下代码,用于在加载经过身份验证的请求 url 之前复制 cookie -

        let cookieGroup = DispatchGroup()
        for cookie in cookieList {
            cookieGroup.enter()
            dataStore.httpCookieStore.setCookie(cookie) { cookieGroup.leave() }
        }
        cookieGroup.notify(queue: DispatchQueue.main) {
            config.websiteDataStore = dataStore
            completion(config)
        }

并且在 cookie (notice isSecure: FALSE) 下面无法设置,因此无法执行平衡leave(),因此从未执行过notify块。

<NSHTTPCookie
    version:1
    name:TESTNAME
    value:BD61035906F6FFFF79D6CEF1F8FFD74ACD03CFC76A758FBBB78C8BC3D6C2C4C3F7B239BBE8C7C3A6FBEF1D903B5AE4FFFF50B9749C2C3593DC2D36FA0CBD695296EC958A
    expiresDate:'2019-05-08 16:10:43 +0000'
    created:'2019-05-07 16:10:43 +0000'
    sessionOnly:FALSE
    domain:SOME_DOMAIN_TEST
    partition:none
    sameSite:none
    path:/
    isSecure:FALSE
 path:"/" isSecure:FALSE>

(更改了上面的名称和域值以混淆来源)

于 2019-05-07T19:27:56.090 回答