我试图从一个UIWebView切换现有应用WKWebView。 目前的应用程序管理用户登录/ Web视图之外的会议,并为验证到的NSHTTPCookieStore所需的cookie。 不幸的是新WKWebView不使用从NSHTTPCookieStorage饼干。 有另一种方式来实现这一目标?
Answer 1:
编辑适用于iOS 11+只
使用WKHTTPCookieStore :
let cookie = HTTPCookie(properties: [
.domain: "example.com",
.path: "/",
.name: "MyCookieName",
.value: "MyCookieValue",
.secure: "TRUE",
.expires: NSDate(timeIntervalSinceNow: 31556926)
])!
webView.configuration.websiteDataStore.httpCookieStore.setCookie(cookie)
既然你是他们在从HTTPCookeStorage拉,你可以这样做:
let cookies = HTTPCookieStorage.shared.cookies ?? []
for (cookie) in cookies {
webView.configuration.websiteDataStore.httpCookieStore.setCookie(cookie)
}
旧的答案iOS的10及以下
如果你需要你的cookies要在初始加载请求设置,你可以把它们放在NSMutableURLRequest。 由于Cookie只是一个特殊格式的请求头这可以像这样实现:
WKWebView * webView = /*set up your webView*/
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://example.com/index.html"]];
[request addValue:@"TeskCookieKey1=TeskCookieValue1;TeskCookieKey2=TeskCookieValue2;" forHTTPHeaderField:@"Cookie"];
// use stringWithFormat: in the above line to inject your values programmatically
[webView loadRequest:request];
如果您需要在页面上后续的AJAX请求有自己的一套饼干,这可以通过简单地使用WKUserScript到通过JavaScript在文件编程设定的值开始,像这样来实现:
WKUserContentController* userContentController = WKUserContentController.new;
WKUserScript * cookieScript = [[WKUserScript alloc]
initWithSource: @"document.cookie = 'TeskCookieKey1=TeskCookieValue1';document.cookie = 'TeskCookieKey2=TeskCookieValue2';"
injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
// again, use stringWithFormat: in the above line to inject your values programmatically
[userContentController addUserScript:cookieScript];
WKWebViewConfiguration* webViewConfig = WKWebViewConfiguration.new;
webViewConfig.userContentController = userContentController;
WKWebView * webView = [[WKWebView alloc] initWithFrame:CGRectMake(/*set your values*/) configuration:webViewConfig];
结合这两种技术应该给你足够的工具从原生应用土地出让Cookie值Web视图土地。 你可以找到更多信息的JavaScript API Mozilla的网页上的cookie ,如果你需要一些更先进的饼干。
是的它吮吸,苹果不支持许多UIWebView的一大乐事 。 不知道他们是否会永远支持他们,但我希望他们很快就会在此。 希望这可以帮助!
Answer 2:
摆弄后这个答案 (这是飞驰的有益:)我们不得不做一些修改:
- 我们需要的Web视图处理多个域无泄露这些领域之间的私人cookie信息
- 我们需要它来履行安全cookie
- 如果服务器更改cookie的值,我们希望我们的应用程序,以了解它在
NSHTTPCookieStorage
- 如果服务器更改cookie的值,我们不希望我们的脚本来重置它回到它原来的价值,当你点击一个链接/ AJAX等。
所以,我们修改我们的代码是这样;
创建请求
NSMutableURLRequest *request = [originalRequest mutableCopy];
NSString *validDomain = request.URL.host;
const BOOL requestIsSecure = [request.URL.scheme isEqualToString:@"https"];
NSMutableArray *array = [NSMutableArray array];
for (NSHTTPCookie *cookie in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]) {
// Don't even bother with values containing a `'`
if ([cookie.name rangeOfString:@"'"].location != NSNotFound) {
NSLog(@"Skipping %@ because it contains a '", cookie.properties);
continue;
}
// Is the cookie for current domain?
if (![cookie.domain hasSuffix:validDomain]) {
NSLog(@"Skipping %@ (because not %@)", cookie.properties, validDomain);
continue;
}
// Are we secure only?
if (cookie.secure && !requestIsSecure) {
NSLog(@"Skipping %@ (because %@ not secure)", cookie.properties, request.URL.absoluteString);
continue;
}
NSString *value = [NSString stringWithFormat:@"%@=%@", cookie.name, cookie.value];
[array addObject:value];
}
NSString *header = [array componentsJoinedByString:@";"];
[request setValue:header forHTTPHeaderField:@"Cookie"];
// Now perform the request...
这可以确保在第一次请求已设置,而不发送从共享存储是用于其他领域的任何cookie正确的Cookie,并没有发送任何安全cookie到不安全的请求。
进一步处理的请求
我们还需要确保其他请求都饼干设置。 这是使用其上检查,看看是否有一个cookie集,如果没有,将其设置为在有价证券负荷运行的脚本进行NSHTTPCookieStorage
。
// Get the currently set cookie names in javascriptland
[script appendString:@"var cookieNames = document.cookie.split('; ').map(function(cookie) { return cookie.split('=')[0] } );\n"];
for (NSHTTPCookie *cookie in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]) {
// Skip cookies that will break our script
if ([cookie.value rangeOfString:@"'"].location != NSNotFound) {
continue;
}
// Create a line that appends this cookie to the web view's document's cookies
[script appendFormat:@"if (cookieNames.indexOf('%@') == -1) { document.cookie='%@'; };\n", cookie.name, cookie.wn_javascriptString];
}
WKUserContentController *userContentController = [[WKUserContentController alloc] init];
WKUserScript *cookieInScript = [[WKUserScript alloc] initWithSource:script
injectionTime:WKUserScriptInjectionTimeAtDocumentStart
forMainFrameOnly:NO];
[userContentController addUserScript:cookieInScript];
...
// Create a config out of that userContentController and specify it when we create our web view.
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
config.userContentController = userContentController;
self.webView = [[WKWebView alloc] initWithFrame:webView.bounds configuration:config];
用饼干对付变化
我们还需要处理服务器改变一个cookie的值。 这意味着将另一个脚本再打了,我们正在创建更新我们的Web视图的NSHTTPCookieStorage
。
WKUserScript *cookieOutScript = [[WKUserScript alloc] initWithSource:@"window.webkit.messageHandlers.updateCookies.postMessage(document.cookie);"
injectionTime:WKUserScriptInjectionTimeAtDocumentStart
forMainFrameOnly:NO];
[userContentController addUserScript:cookieOutScript];
[userContentController addScriptMessageHandler:webView
name:@"updateCookies"];
和实现委托方法来更新已经改变,确保我们只能从当前域更新饼干任何cookie!
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
NSArray<NSString *> *cookies = [message.body componentsSeparatedByString:@"; "];
for (NSString *cookie in cookies) {
// Get this cookie's name and value
NSArray<NSString *> *comps = [cookie componentsSeparatedByString:@"="];
if (comps.count < 2) {
continue;
}
// Get the cookie in shared storage with that name
NSHTTPCookie *localCookie = nil;
for (NSHTTPCookie *c in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:self.wk_webView.URL]) {
if ([c.name isEqualToString:comps[0]]) {
localCookie = c;
break;
}
}
// If there is a cookie with a stale value, update it now.
if (localCookie) {
NSMutableDictionary *props = [localCookie.properties mutableCopy];
props[NSHTTPCookieValue] = comps[1];
NSHTTPCookie *updatedCookie = [NSHTTPCookie cookieWithProperties:props];
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:updatedCookie];
}
}
}
这似乎解决我们的Cookie问题,而我们不必处理每一个我们使用WKWebView不同的地方。 现在,我们可以只使用此代码作为帮手来创建我们的网页视图,并透明地更新NSHTTPCookieStorage
我们。
编辑:原来我用NSHTTPCookie一个私人的类别 - 下面的代码:
- (NSString *)wn_javascriptString {
NSString *string = [NSString stringWithFormat:@"%@=%@;domain=%@;path=%@",
self.name,
self.value,
self.domain,
self.path ?: @"/"];
if (self.secure) {
string = [string stringByAppendingString:@";secure=true"];
}
return string;
}
Answer 3:
对我的工作
func webView(webView: WKWebView, decidePolicyForNavigationAction navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) {
let headerFields = navigationAction.request.allHTTPHeaderFields
var headerIsPresent = contains(headerFields?.keys.array as! [String], "Cookie")
if headerIsPresent {
decisionHandler(WKNavigationActionPolicy.Allow)
} else {
let req = NSMutableURLRequest(URL: navigationAction.request.URL!)
let cookies = yourCookieData
let values = NSHTTPCookie.requestHeaderFieldsWithCookies(cookies)
req.allHTTPHeaderFields = values
webView.loadRequest(req)
decisionHandler(WKNavigationActionPolicy.Cancel)
}
}
Answer 4:
饼干必须在配置之前设置WKWebView
创建。 否则,即使有WKHTTPCookieStore
的setCookie
完成处理,饼干就不能可靠地同步到网络视图。 这又回到了这条线从文档上WKWebViewConfiguration
@NSCopying var configuration: WKWebViewConfiguration { get }
这@NSCopying
是有点深拷贝。 实现超越我,但最终的结果是,除非你在初始化之前的WebView设置cookie,你不能上的Cookie在那里算。 因为初始化角度的异步过程这可以变得复杂应用架构。 你最终会像这样的东西
extension WKWebViewConfiguration {
/// Async Factory method to acquire WKWebViewConfigurations packaged with system cookies
static func cookiesIncluded(completion: @escaping (WKWebViewConfiguration?) -> Void) {
let config = WKWebViewConfiguration()
guard let cookies = HTTPCookieStorage.shared.cookies else {
completion(config)
return
}
// Use nonPersistent() or default() depending on if you want cookies persisted to disk
// and shared between WKWebViews of the same app (default), or not persisted and not shared
// across WKWebViews in the same app.
let dataStore = WKWebsiteDataStore.nonPersistent()
let waitGroup = DispatchGroup()
for cookie in cookies {
waitGroup.enter()
dataStore.httpCookieStore.setCookie(cookie) { waitGroup.leave() }
}
waitGroup.notify(queue: DispatchQueue.main) {
config.websiteDataStore = dataStore
completion(config)
}
}
}
然后使用它像
override func loadView() {
view = UIView()
WKWebViewConfiguration.cookiesIncluded { [weak self] config in
let webView = WKWebView(frame: .zero, configuration: webConfiguration)
webView.load(request)
self.view = webView
}
}
上面的例子中推迟视图创建,直到最后可能的时刻,另一种解决方案是创建的配置或网页视图提前做好和创建视图控制器的前处理异步性质。
最后要注意的:一旦你创建这个web视图,您设置了松散到野外,你不能在不使用所描述的方法添加更多的cookie 这个答案 。 但是,您可以使用WKHTTPCookieStoreObserver
API来至少观察变化发生在饼干。 所以,如果一个会话cookie获取web视图更新,您可以手动更新系统的HTTPCookieStorage
这个新的cookie如果需要的话。
欲了解更多关于此,请跳到18:00在这个2017年的WWDC会议自定义Web内容加载 。 在这次会议开始时,有一个欺骗性的代码示例它忽略了web视图应在完成处理程序创建的事实。
cookieStore.setCookie(cookie!) {
webView.load(loggedInURLRequest)
}
在18:00的现场演示阐明了这一点。
编辑作为莫哈韦7 Beta版和iOS测试版12 7,至少,我看到与cookies更加一致的行为。 该setCookie(_:)
方法,即使出现后,允许设置cookie WKWebView
已创建。 我发现它虽然很重要, 不要触摸 processPool
在所有变量。 没有创建额外的游泳池和时属性为好独自一人时的Cookie设置功能效果最好。 我认为它是安全的,说我们有由于WebKit中的一些错误的问题。
Answer 5:
这里是我的版本Mattrs解决方案,斯威夫特从HTTPCookieStorage注入所有的cookies。 这主要是做一个注入身份验证cookie来创建一个用户会话。
public func setupWebView() {
let userContentController = WKUserContentController()
if let cookies = HTTPCookieStorage.shared.cookies {
let script = getJSCookiesString(for: cookies)
let cookieScript = WKUserScript(source: script, injectionTime: .atDocumentStart, forMainFrameOnly: false)
userContentController.addUserScript(cookieScript)
}
let webViewConfig = WKWebViewConfiguration()
webViewConfig.userContentController = userContentController
self.webView = WKWebView(frame: self.webViewContainer.bounds, configuration: webViewConfig)
}
///Generates script to create given cookies
public func getJSCookiesString(for cookies: [HTTPCookie]) -> String {
var result = ""
let dateFormatter = DateFormatter()
dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
dateFormatter.dateFormat = "EEE, d MMM yyyy HH:mm:ss zzz"
for cookie in cookies {
result += "document.cookie='\(cookie.name)=\(cookie.value); domain=\(cookie.domain); path=\(cookie.path); "
if let date = cookie.expiresDate {
result += "expires=\(dateFormatter.stringFromDate(date)); "
}
if (cookie.secure) {
result += "secure; "
}
result += "'; "
}
return result
}
Answer 6:
斯威夫特3更新:
func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
if let urlResponse = navigationResponse.response as? HTTPURLResponse,
let url = urlResponse.url,
let allHeaderFields = urlResponse.allHeaderFields as? [String : String] {
let cookies = HTTPCookie.cookies(withResponseHeaderFields: allHeaderFields, for: url)
HTTPCookieStorage.shared.setCookies(cookies , for: urlResponse.url!, mainDocumentURL: nil)
decisionHandler(.allow)
}
}
Answer 7:
集饼干
self.webView.evaluateJavaScript("document.cookie='access_token=your token';domain='your domain';") { (data, error) -> Void in
self.webView.reload()
}
删除的cookie
self.webView.evaluateJavaScript("document.cookie='access_token=';domain='your domain';") { (data, error) -> Void in
self.webView.reload()
}
Answer 8:
在iOS中11,你现在可以管理的cookie :),看到这个会话: https://developer.apple.com/videos/play/wwdc2017/220/
Answer 9:
通过各种答案寻找这里和不具有任何成功后,我通过WebKit的文档梳理并偶然发现了requestHeaderFields
上静态方法HTTPCookie
,该饼干的阵列转换成适合于报头字段的格式。 与此相结合将mattr的洞察力更新的URLRequest
与cookie头加载它之前让我通过了终点线。
雨燕4.1:
var request = URLRequest(url: URL(string: "https://example.com/")!)
let headers = HTTPCookie.requestHeaderFields(with: cookies)
for (name, value) in headers {
request.addValue(value, forHTTPHeaderField: name)
}
let webView = WKWebView(frame: self.view.frame)
webView.load(request)
为了使这个更简单,使用扩展:
extension WKWebView {
func load(_ request: URLRequest, with cookies: [HTTPCookie]) {
var request = request
let headers = HTTPCookie.requestHeaderFields(with: cookies)
for (name, value) in headers {
request.addValue(value, forHTTPHeaderField: name)
}
load(request)
}
}
现在,它只是变成了:
let request = URLRequest(url: URL(string: "https://example.com/")!)
let webView = WKWebView(frame: self.view.frame)
webView.load(request, with: cookies)
这个扩展也提供LionheartExtensions如果你只是想一个简易的解决方案。 干杯!
Answer 10:
背后的原因张贴了这个答案是我尝试了许多解决方案,但没有一个能正常工作,大多数的答案在哪里必须设置cookie的首次情况下无法正常工作,并得到了结果的cookie不同步一次,请使用此解决方案是两个工作的iOS> = 11.0 <= 11的iOS直到8.0,也与同步的cookie第一次工作。
对于iOS> = 11.0 - 4.2斯威夫特
GET HTTP cookies和在wkwebview cookie存储这样的方式设置,这是非常棘手的点加载wkwebview您的要求,必须发送加载请求时,会饼干完全设置,这里是函数,我写的。
在完成关闭通话功能调用加载网页流量。 FYI此函数只处理的iOS> = 11.0
self.WwebView.syncCookies {
if let request = self.request {
self.WwebView.load(request)
}
}
下面是实施syncCookies功能。
func syncCookies(completion:@escaping ()->Void) {
if #available(iOS 11.0, *) {
if let yourCookie = "HERE_YOUR_HTTP_COOKIE_OBJECT" {
self.configuration.websiteDataStore.httpCookieStore.setCookie(yourCookie, completionHandler: {
completion()
})
}
} else {
//Falback just sent
completion()
}
}
对于iOS 8至11的iOS
你需要设置你需要通过使用WKUserScript设置两个时间饼干之一,不要忘记在请求添加饼干,以及一些额外的东西,否则你的cookie不同步的第一次,你会看到你的网页无法正确加载第一次。 这是我发现支持Cookie的iOS 8.0赫克
之前你Wkwebview创建对象。
func setUpWebView() {
let userController: WKUserContentController = WKUserContentController.init()
if IOSVersion.SYSTEM_VERSION_LESS_THAN(version: "11.0") {
if let cookies = HTTPCookieStorage.shared.cookies {
if let script = getJSCookiesString(for: cookies) {
cookieScript = WKUserScript(source: script, injectionTime: .atDocumentStart, forMainFrameOnly: false)
userController.addUserScript(cookieScript!)
}
}
}
let webConfiguration = WKWebViewConfiguration()
webConfiguration.processPool = BaseWebViewController.processPool
webConfiguration.userContentController = userController
let customFrame = CGRect.init(origin: CGPoint.zero, size: CGSize.init(width: 0.0, height: self.webContainerView.frame.size.height))
self.WwebView = WKWebView (frame: customFrame, configuration: webConfiguration)
self.WwebView.translatesAutoresizingMaskIntoConstraints = false
self.webContainerView.addSubview(self.WwebView)
self.WwebView.uiDelegate = self
self.WwebView.navigationDelegate = self
self.WwebView.allowsBackForwardNavigationGestures = true // A Boolean value indicating whether horizontal swipe gestures will trigger back-forward list navigations
self.WwebView.addObserver(self, forKeyPath: #keyPath(WKWebView.estimatedProgress), options: .new, context: nil)
self.view.addConstraint(NSLayoutConstraint(item: WwebView, attribute: .trailing, relatedBy: .equal, toItem: self.webContainerView, attribute: .trailing, multiplier: 1, constant: 0))
self.view.addConstraint(NSLayoutConstraint(item: WwebView, attribute: .leading, relatedBy: .equal, toItem: self.webContainerView, attribute: .leading, multiplier: 1, constant: 0))
self.view.addConstraint(NSLayoutConstraint(item: WwebView, attribute: .top, relatedBy: .equal, toItem: self.webContainerView, attribute: .top, multiplier: 1, constant: 0))
self.view.addConstraint(NSLayoutConstraint(item: WwebView, attribute: .bottom, relatedBy: .equal, toItem: self.webContainerView, attribute: .bottom, multiplier: 1, constant: 0))
}
专注于这个功能getJSCookiesString
public func getJSCookiesString(for cookies: [HTTPCookie]) -> String? {
var result = ""
let dateFormatter = DateFormatter()
dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
dateFormatter.dateFormat = "EEE, d MMM yyyy HH:mm:ss zzz"
for cookie in cookies {
if cookie.name == "yout_cookie_name_want_to_sync" {
result += "document.cookie='\(cookie.name)=\(cookie.value); domain=\(cookie.domain); path=\(cookie.path); "
if let date = cookie.expiresDate {
result += "expires=\(dateFormatter.string(from: date)); "
}
if (cookie.isSecure) {
result += "secure; "
}
result += "'; "
}
}
return result
}
下面是其他的步骤wkuserscript不会立即同步饼干,有很多赫克的加载首次页面的cookie一是重新加载网页视图如果终止的过程,但我不建议使用它,它不适合的观点用户点,到底是当你准备载入的请求设置cookie在请求头,以及这样的方式,不要忘了添加的iOS版本检查。 负载请求之前调用此函数。
request?.addCookies()
我写扩展的URLRequest
extension URLRequest {
internal mutating func addCookies() {
//"appCode=anAuY28ucmFrdXRlbi5yZXdhcmQuaW9zLXpOQlRTRmNiejNHSzR0S0xuMGFRb0NjbUg4Ql9JVWJH;rpga=kW69IPVSYZTo0JkZBicUnFxC1g5FtoHwdln59Z5RNXgJoMToSBW4xAMqtf0YDfto;rewardadid=D9F8CE68-CF18-4EE6-A076-CC951A4301F6;rewardheader=true"
var cookiesStr: String = ""
if IOSVersion.SYSTEM_VERSION_LESS_THAN(version: "11.0") {
let mutableRequest = ((self as NSURLRequest).mutableCopy() as? NSMutableURLRequest)!
if let yourCookie = "YOUR_HTTP_COOKIE_OBJECT" {
// if have more than one cookies dont forget to add ";" at end
cookiesStr += yourCookie.name + "=" + yourCookie.value + ";"
mutableRequest.setValue(cookiesStr, forHTTPHeaderField: "Cookie")
self = mutableRequest as URLRequest
}
}
}
}
现在你准备去测试iOS版> 8
Answer 11:
请找出其中最有可能会为你工作开箱即用的解决方案。 基本上它的修改和更新的雨燕4 @ user3589213的答案 。
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
let headerKeys = navigationAction.request.allHTTPHeaderFields?.keys
let hasCookies = headerKeys?.contains("Cookie") ?? false
if hasCookies {
decisionHandler(.allow)
} else {
let cookies = HTTPCookie.requestHeaderFields(with: HTTPCookieStorage.shared.cookies ?? [])
var headers = navigationAction.request.allHTTPHeaderFields ?? [:]
headers += cookies
var req = navigationAction.request
req.allHTTPHeaderFields = headers
webView.load(req)
decisionHandler(.cancel)
}
}
Answer 12:
为XHR请求更好的修复程序显示在这里
斯威夫特4版:
func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Swift.Void) {
guard
let response = navigationResponse.response as? HTTPURLResponse,
let url = navigationResponse.response.url
else {
decisionHandler(.cancel)
return
}
if let headerFields = response.allHeaderFields as? [String: String] {
let cookies = HTTPCookie.cookies(withResponseHeaderFields: headerFields, for: url)
cookies.forEach { (cookie) in
HTTPCookieStorage.shared.setCookie(cookie)
}
}
decisionHandler(.allow)
}
Answer 13:
如果有人使用Alamofire,那么这是更好的解决方案。
let cookies = Alamofire.SessionManager.default.session.configuration.httpCookieStorage?.cookies(for: URL(string: BASE_URL)!)
for (cookie) in cookies ?? [] {
webView.configuration.websiteDataStore.httpCookieStore.setCookie(cookie)
}
Answer 14:
This works for me: After setcookies , add fetchdatarecords
let cookiesSet = NetworkProvider.getCookies(forKey :
PaywallProvider.COOKIES_KEY, completionHandler: nil)
let dispatchGroup = DispatchGroup()
for (cookie) in cookiesSet {
if #available(iOS 11.0, *) {
dispatchGroup.enter()
self.webView.configuration.websiteDataStore.httpCookieStore.setCookie(cookie){
dispatchGroup.leave()
print ("cookie added: \(cookie.description)")
}
} else {
// TODO Handle ios 10 Fallback on earlier versions
}
}
dispatchGroup.notify(queue: .main, execute: {
self.webView.configuration.websiteDataStore.fetchDataRecords(ofTypes:
WKWebsiteDataStore.allWebsiteDataTypes()) { records in
records.forEach { record in
print("[WebCacheCleaner] Record \(record)")
}
self.webView.load(URLRequest(url:
self.dataController.premiumArticleURL ,
cachePolicy:NSURLRequest.CachePolicy.reloadIgnoringLocalAndRemoteCacheData,
timeoutInterval: 10.0))
}
})
}
Answer 15:
我已经尝试了所有上述问题的答案,但他们没有工作。 这么多的尝试后,我终于找到了一个可靠的方式来设置WKWebview饼干。
首先,你必须创建WKProcessPool的一个实例,并将其设置为将被用于初始化WkWebview本身WKWebViewConfiguration:
private lazy var mainWebView: WKWebView = {
let webConfiguration = WKWebViewConfiguration()
webConfiguration.processPool = WKProcessPool()
let webView = WKWebView(frame: .zero, configuration: webConfiguration)
webView.navigationDelegate = self
return webView
}()
设置WKProcessPool是这里最重要的一步。 WKWebview利用进程隔离的 - 这意味着它运行在一个不同的过程比你的应用程序的过程。 这有时会导致冲突并防止您的Cookie被与WKWebview正确同步。
现在,让我们来看看定义WKProcessPool
与web视图相关联的处理池是由它的网络视图配置中指定。 每个Web视图中给出了自己的网页内容的过程,直到达到实现定义的过程中限制; 在这之后,用相同的进程池Web视图结束共享Web内容的过程。
注意最后一句,如果你打算使用子请求相同的WKWebview
用相同的进程池Web视图结束共享Web内容的过程
我的意思是,如果你不每次使用WKProcessPool的同一个实例配置为相同的域(也许你有一个包含WKWebView一个VC A中的WKWebView,你要创建在不同的地方VC A的不同实例),可以有冲突设置cookie。 为了解决这个问题,加载域B一WKWebView第一创作WKProcessPool后,我把它保存在一个独立的,并使用相同的WKProcessPool每次我有时间来创建加载同一个域B中的WKWebView
private lazy var mainWebView: WKWebView = {
let webConfiguration = WKWebViewConfiguration()
if Enviroment.shared.processPool == nil {
Enviroment.shared.processPool = WKProcessPool()
}
webConfiguration.processPool = Enviroment.shared.processPool!
webConfiguration.processPool = WKProcessPool()
let webView = WKWebView(frame: .zero, configuration: webConfiguration)
webView.navigationDelegate = self
return webView
}()
在初始化处理后,就可以加载完成区块内的的URLRequest httpCookieStore.setCookie
。 在这里, 你必须附上cookie来请求头 ,否则将无法正常工作。
P / S:我的丹Loewenherz偷以上从梦幻般的答案扩展
mainWebView.configuration.websiteDataStore.httpCookieStore.setCookie(your_cookie) {
self.mainWebView.load(your_request, with: [your_cookie])
}
extension WKWebView {
func load(_ request: URLRequest, with cookies: [HTTPCookie]) {
var request = request
let headers = HTTPCookie.requestHeaderFields(with: cookies)
for (name, value) in headers {
request.addValue(value, forHTTPHeaderField: name)
}
load(request)
}
}
Answer 16:
当添加乘饼干的物品,你可以做这样的:( path
和domain
需要为每个项目)
NSString *cookie = [NSString stringWithFormat:@"document.cookie = 'p1=%@;path=/;domain=your.domain;';document.cookie = 'p2=%@;path=/;domain=your.domain;';document.cookie = 'p3=%@;path=/;domain=your.domain;';", p1_string, p2_string, p3_string];
WKUserScript *cookieScript = [[WKUserScript alloc]
initWithSource:cookie
injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
[userContentController addUserScript:cookieScript];
否则,只有第一个Cookie项目将被设置。