筆者公司最近為了快速出一款app织咧,采用UINavigationController+WebView或者NavigationController+UITabbarVC+WebView的方式镜撩,登錄頁面使用原APP西篓,這樣就不可避免的需要使用cookie與Html5交互(這里使用的WebViewJavascriptBridge)
普通的webView 是通用 NSHTTPCookieStorage 里面的cookie
所以set cookie 比較簡單 這里不再重復(fù)
WKWebView 擁有自己的私有存儲背苦,不會將 Cookie 存入到標(biāo)準(zhǔn)的 Cookie 容器 NSHTTPCookieStorage 所以需要自己儲存一套 cookie 筆者是直接 在userdefaults
func saveCookieWithDate(response:Response)->(){
let headerFields = response.response?.allHeaderFields as! [String: String]
let url = response.request?.url
let cookies = HTTPCookie.cookies(withResponseHeaderFields: headerFields, for: url!)
let cookieData = NSKeyedArchiver.archivedData(withRootObject: cookies)
let cookieDictionary = ["cookie":cookieData] as [String : Any]
let userDefaults = UserDefaults.standard
userDefaults.set(cookieDictionary, forKey: CurrentUserCookie)
userDefaults.synchronize()
}
實(shí)踐發(fā)現(xiàn) WKWebView 實(shí)例其實(shí)也會將 Cookie 存儲于 NSHTTPCookieStorage 中床估,但存儲時機(jī)有延遲赵颅,在iOS 8上,當(dāng)頁面跳轉(zhuǎn)的時候绑改,當(dāng)前頁面的 Cookie 會寫入 NSHTTPCookieStorage 中谢床,而在 iOS 10 上,JS 執(zhí)行 document.cookie 或服務(wù)器 set-cookie 注入的 Cookie 會很快同步到 NSHTTPCookieStorage 中厘线,F(xiàn)ireFox 工程師曾建議通過 reset WKProcessPool 來觸發(fā) Cookie 同步到 NSHTTPCookieStorage 中识腿,實(shí)踐發(fā)現(xiàn)不起作用,并可能會引發(fā)當(dāng)前頁面 session cookie 丟失等問題造壮。
WKWebView Cookie 問題在于 WKWebView 發(fā)起的請求不會自動帶上存儲于 NSHTTPCookieStorage 容器中的 Cookie渡讼。
這里先說一下百度來的資料
1.load request 的時候添加cookie
var urlRequest = URLRequest(url: url)
urlRequest.addValue("testwkcookie = testwkcookievalue", forHTTPHeaderField: "Cookie")
urlRequest.addValue("testwktoken = testwktokenvalue", forHTTPHeaderField: "Cookie")
self.webView.load(urlRequest)
(無效)
2.在WKUserContentController中,所有使用到WKUserScript耳璧。WKUserContentController是用于與JS交互的類成箫,而所注入的JS是WKUserScript對象。
let cookieString = "testwkcookie = testwkcookievalue; testToken = testwktokenvalue "
let cookieScript = WKUserScript(source: cookieString, injectionTime: WKUserScriptInjectionTime.atDocumentStart, forMainFrameOnly: false)
var userContent = WKUserContentController()
userContent.addUserScript(cookieScript)
(無效)
到這里筆者已經(jīng)浪費(fèi)了 2個小時了(手動微笑)最后和 h5的小伙伴 問了 一下 cookie的加載地點(diǎn) 和 set時機(jī) (他自己會手動修改這個)最后得到了答案:
在通過 document.cookie 設(shè)置 Cookie 解決后續(xù)頁面(同域)Ajax旨枯、iframe 請求的 Cookie 問題
(但是 注意:document.cookie()無法跨域設(shè)置 cookie) 我們這里不涉及所以就忽略了
let cookieString = "document.cookie = 'fromapp=ios';document.cookie = 'channel=appstore';"
#warning 然而這里的單引號一定要注意是英文的蹬昌,不要問我為什么告訴你這個(手動微笑)可以去看一下網(wǎng)頁的cookie 格式
let cookieScript = WKUserScript(source: cookieString, injectionTime: WKUserScriptInjectionTime.atDocumentStart, forMainFrameOnly: false)
var userContent = WKUserContentController()
userContent.addUserScript(cookieScript)
成功 !E矢簟皂贩!
最后貼一下 代碼塊 (直接復(fù)制就好了)
func setWebCookie(userContent:WKUserContentController) {
let userDefaults = UserDefaults.standard
guard let cookieDictionary = userDefaults .object(forKey: hqCurrentUserCookie) as?Dictionary<String, Any> else {
return
}
let cookieData = cookieDictionary["cookie"] as! Data
guard let cookies = NSKeyedUnarchiver .unarchiveObject(with: cookieData ) as? [HTTPCookie] else
{
return
}
var cookieString = ""
for cookie in cookies{
cookieString.append("document.cookie =" + "'" + cookie.name + "=" + cookie.value + "';")
}
let cookieScript = WKUserScript(source: cookieString, injectionTime: WKUserScriptInjectionTime.atDocumentStart, forMainFrameOnly: false)
userContent.addUserScript(cookieScript)
}
最后筆者又查到了一種 在iOS11中,蘋果新增加了用于WKWebview Cookie存取操作的WKHTTPCookieStore昆汹。
let cookie = HTTPCookie.init(properties: [
.domain:"172.16.10.26",
.path:"/src/p/index/index.html",
.version:0,
.expires:Date.init(timeIntervalSinceNow: 30*60*60),
.name:"username",
.value:"zhanggui33"
])
let cookieStore = myWKWebView.configuration.websiteDataStore.httpCookieStore
cookieStore.setCookie(cookie!) {
self.myWKWebView.load(URLRequest.init(url: URL.init(string: "http://172.16.10.26:3333/src/p/index/index.html")!))
}