WKHTTPCookieStore HTTPCookieStorage同步类 [英] WKHTTPCookieStore HTTPCookieStorage synchronization class
本文介绍了WKHTTPCookieStore HTTPCookieStorage同步类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
WKWebView
,一个在主应用程序中,另一个在应用程序扩展中。我希望它们共享同一个Cookie存储区。
Apple API有两个不同的Cookie存储类:WKHTTPCookieStore
和HTTPCookieStorage
。
Apple还有sharedCookieStorage(forGroupContainerIdentifier identifier: String) -> HTTPCookieStorage
forURLSession
s(非WKWebView
s)可跨应用程序/生成目标/扩展使用。
我的计划是将一个WKWebKit
Cookie传输到sharedCookieStorage,然后再传输到另一个WKWebKit
Cookie存储区。
在我编写之前,有没有人有一个简单的包装类来接受、观察并保持它们的同步?
或者有没有其他更简单的方法来完成这一看似非常常见的用例?
推荐答案
这是我放在一起的。需要牢记的重要事项:
WKWebView
Cookie是异步设置和获取的,因此回调次数- 有一个观察者类附加到
WKHTTPCookieStore
。它并不完美,但有cookiesDidChange
方法可用于手动更新,比如在页面加载后 - 您应该在
addCookieStore
回调中实例化并加载WKWebView
,以确保在加载页面之前同步存储 - 添加的存储区最初与添加的第一个存储区同步。您应该嵌套
addCookieStore
回调以确保正确的顺序
(很抱歉,由于兼容性原因,我无法使用合并)
编码:
import WebKit
import Foundation
class CookieSync : NSObject, WKHTTPCookieStoreObserver {
var wkStores = [WKHTTPCookieStore]();
var sessionStores = [HTTPCookieStorage]();
static let debug = false
//The first store added is the canon
func addCookieStore(_ store: WKHTTPCookieStore, callback:(()->())?) {
wkStores.append(store)
store.getAllCookies { (cookies) in
if CookieSync.debug { print("Adding WK:(cookies.count)") }
store.add(self)
if self.sessionStores.count > 0 {
self.synchronizeAll(self.sessionStores[0]) {
store.getAllCookies { (cookies) in
if CookieSync.debug { print("Added WK:(cookies.count)") }
callback?()
}
}
} else if self.wkStores.count > 1 {
self.synchronizeAll(self.wkStores[0]) {
store.getAllCookies { (cookies) in
if CookieSync.debug { print("Added WK:(cookies.count)") }
callback?()
}
}
} else {
callback?()
}
}
}
//The first store added is the canon
func addCookieStore(_ store: HTTPCookieStorage, callback:(()->())?) {
sessionStores.append(store)
if CookieSync.debug { print("Adding S:(store.cookies?.count ?? 0)") }
if wkStores.count > 0 {
synchronizeAll(wkStores[0]) {
if CookieSync.debug { print("Added S:(store.cookies?.count ?? 0)") }
callback?()
}
} else if sessionStores.count > 1 {
synchronizeAll(sessionStores[0]) {
if CookieSync.debug { print("Added S:(store.cookies?.count ?? 0)") }
callback?()
}
} else {
callback?()
}
}
//There is no Observer callback for HTTPCookieStorage
func cookiesDidChange(in cookieStore: HTTPCookieStorage) {
synchronizeAll(cookieStore) {
if CookieSync.debug { print("Synced S:(cookieStore.cookies?.count ?? 0)") }
}
}
func cookiesDidChange(in cookieStore: WKHTTPCookieStore) {
synchronizeAll(cookieStore) {
cookieStore.getAllCookies { (cookies) in
if CookieSync.debug { print("Synced WK:(cookies.count)") }
for cookie in cookies {
if CookieSync.debug { print("(cookie.name) = (cookie.value)") }
}
}
}
}
//Private
fileprivate func synchronizeAll(_ to: WKHTTPCookieStore, callback:(()->())?) {
let dispatch = DispatchGroup()
let queue = Thread.isMainThread ? DispatchQueue.main : DispatchQueue(label: "cookie_sync1")
for store in self.wkStores {
if store == to { continue }
dispatch.enter()
self.removeAllCookies(store) {
dispatch.enter()
to.getAllCookies { (cookies) in
for cookie in cookies {
dispatch.enter()
store.setCookie(cookie) {
dispatch.leave()
}
}
dispatch.leave()
}
dispatch.leave()
}
}
for store in self.sessionStores {
self.removeAllCookies(store)
dispatch.enter()
to.getAllCookies { (cookies) in
for cookie in cookies {
store.setCookie(cookie)
}
dispatch.leave()
}
}
dispatch.notify(queue: queue) {
callback?()
}
}
fileprivate func synchronizeAll(_ to: HTTPCookieStorage, callback:(()->())?) {
guard let cookies = to.cookies else { callback?(); return; }
let queue = Thread.isMainThread ? DispatchQueue.main : DispatchQueue(label: "cookie_sync2")
let dispatch = DispatchGroup()
for store in self.sessionStores {
if store == to { continue }
self.removeAllCookies(store)
for cookie in cookies {
store.setCookie(cookie)
}
}
for store in self.wkStores {
dispatch.enter()
self.removeAllCookies(store) {
for cookie in cookies {
dispatch.enter()
store.setCookie(cookie) {
dispatch.leave()
}
}
dispatch.leave()
}
}
dispatch.notify(queue: queue) {
callback?()
}
}
fileprivate func removeAllCookies(_ store: WKHTTPCookieStore, callback:(()->())?) {
let queue = Thread.isMainThread ? DispatchQueue.main : DispatchQueue(label: "cookie_delete")
let dispatch = DispatchGroup()
dispatch.enter()
store.getAllCookies { (cookies) in
for cookie in cookies {
dispatch.enter()
store.delete(cookie) {
dispatch.leave()
}
}
dispatch.leave()
}
dispatch.notify(queue: queue) {
callback?()
}
}
fileprivate func removeAllCookies(_ store: HTTPCookieStorage) {
guard let cookies = store.cookies else { return }
for cookie in cookies {
store.deleteCookie(cookie)
}
}
}
这篇关于WKHTTPCookieStore HTTPCookieStorage同步类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文