因为WKWebView是通过WebKit内核进行网络处理的,所以我们的NSHTTPCookieStorage里的Cookie是没办法拿到并带进一个请求的。可以通过下面的方法手动添加:
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://www.baidu.com"]];
NSArray *cookies = [NSHTTPCookieStorage sharedHTTPCookieStorage].cookies;
NSDictionary *requestHeaderFields = [NSHTTPCookie requestHeaderFieldsWithCookies:cookies];
//设置请求头
request.allHTTPHeaderFields = requestHeaderFields;
这种方式只对单个请求有效,一旦URL改变,Cookie还是会丢失,所以我们可以通过WKWebView的代理
- (void)webView: decidePolicyForNavigationAction: decisionHandler:
来对每一个request进行Cookie处理
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
[[WKCookieManager shareManager] fixNewRequestCookieWithRequest:navigationAction.request];
decisionHandler(WKNavigationActionPolicyAllow);
}
- (NSURLRequest *)fixNewRequestCookieWithRequest:(NSURLRequest *)originalRequest{
NSMutableURLRequest *fixedRequest;
if ([originalRequest isKindOfClass:[NSMutableURLRequest class]]) {
fixedRequest = (NSMutableURLRequest *)originalRequest;
} else {
fixedRequest = originalRequest.mutableCopy;
}
//防止Cookie丢失
NSDictionary *dict = [NSHTTPCookie requestHeaderFieldsWithCookies:[NSHTTPCookieStorage sharedHTTPCookieStorage].cookies];
if (dict.count) {
NSMutableDictionary *mDict = originalRequest.allHTTPHeaderFields.mutableCopy;
[mDict setValuesForKeysWithDictionary:dict];
fixedRequest.allHTTPHeaderFields = mDict;
}
return fixedRequest;
}
另外一种方式:
可以在WKWebViewConfiguration的userContentController中注入脚本:
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
WKUserContentController *controller = [[WKUserContentController alloc] init];
[controller addUserScript:[[WKCookieManager shareManager] futhureCookieScript]];
configuration.userContentController = controller;
- (WKUserScript *)futhureCookieScript{
// source 就是我们要调用的 JS 函数或者我们要执行的 JS 代码
// injectionTime 这个参数我们需要指定一个时间,在什么时候把我们在这段 JS 注入到 WebVeiw 中,它是一个枚举值,WKUserScriptInjectionTimeAtDocumentStart 或者 WKUserScriptInjectionTimeAtDocumentEnd
// MainFrameOnly 因为在 JS 中,一个页面可能有多个 frame,这个参数指定我们的 JS 代码是否只在 mainFrame 中生效
- initWithSource:injectionTime:forMainFrameOnly:
WKUserScript * cookieScript = [[WKUserScript alloc] initWithSource:[self cookieString] injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
return cookieScript;
}
- (NSString *)cookieString
{
NSMutableString *script = [NSMutableString string];
[script appendString:@"var cookieNames = document.cookie.split('; ').map(function(cookie) { return cookie.split('=')[0] } );\n"];
for (NSHTTPCookie *cookie in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]) {
if ([cookie.value rangeOfString:@"'"].location != NSNotFound) {
continue;
}
NSString *string = [NSString stringWithFormat:@"%@=%@;domain=%@;path=%@",
cookie.name,
cookie.value,
cookie.domain,
cookie.path ?: @"/"];
if (cookie.secure) {
string = [string stringByAppendingString:@";secure=true"];
}
[script appendFormat:@"if (cookieNames.indexOf('%@') == -1) { document.cookie='%@'; };\n", cookie.name, string];
}
return script;
}
iOS11之后
iOS11之后,有一个更简便的方法:
/*! @abstract Returns the cookie store representing HTTP cookies in this website data store. */
@property (nonatomic, readonly) WKHTTPCookieStore *httpCookieStore API_AVAILABLE(macosx(10.13), ios(11.0));
//发送请求前插入cookie;
NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];
WKHTTPCookieStore *cookieStore = [WKWebsiteDataStore defaultDataStore].httpCookieStore;
if (cookies.count > 0) {
for (NSHTTPCookie *cookie in cookies) {
[cookieStore setCookie:cookie completionHandler:^{
}];
}
}
网友评论