当前项目使用cookie来维护用户登录状态、App版本系统、语言等状态信息。
在UIWebView时代,可以通过NSHTTPCookieStorage
单例很直接的管理客户端cookie。UIWebView的cookie数据会自动和NSHTTPCookieStorage
进行同步。而WKWebView的cookie维护一直为人诟病。只要你维护过相关业务,不同iOS版本上出现的各种cookie的问题一定让你头疼过。
这个Demo提供踩坑折腾几个月之后的解决方案,虽然不是很完整,但是基本满足当前项目需求。核心类WebViewCookieUtil。
通过WKHTTPCookieStore
和WKProcessPool
对cookie进行管理和同步,
当cookie更新时使用WKWebsiteDataStore
的setCookie:completionHandler:
和deleteCookie:completionHandler:
进行cookie更新即可。
详见WebViewCookieUtil
的 +clientCookieDidUpdate:toRemove:
方法
补充:
如果多个使用defaultDataStore
的webView实例指定的WKProcessPool
不同,cookie可能会无法更新到所有的webView中,建议全局使用同一个WKProcessPool
实例。
- 通过
WKUserScript
和WKUserContentController
注入JS代码的方式进行cookie更新。 - 首个请求的cookie需要通过NSMutableRequest设置。
- 更新cookie需要做到如下两个步骤:
- 通过
WKWebsiteDataStore
获取到类型为WKWebsiteDataTypeCookies
的WKWebsiteDataRecord
, 整体删除。 - 从
WKUserContentController
中替换WKUserScript
然后reload整个页面。
- 通过
补充:
该方案不需要设置WKProcessPool
, 如果和高版本iOS一样设置WKProcessPool
单例,会导致仅删除类型为WKWebsiteDataTypeCookies
的WKWebsiteDataRecord
无法删除cookie。
当存在非视图结构中的WKWebView加载网页时,WKHttpCookieStorage
的异步API回调block可能不会被调用或者回调非常慢。目前观察该问题出现在iOS11.3~iOS12.2的系统。如果遇到相同问题可以首先排查是否有多个webView同时加载。
解决成本高的话,可以将该webView的dataStore设置成nonPersistentDataStore
来暂时规避该问题。