WKWebView Cookie共享 OC JS互相调用
WKWebView的Cookie共享在项目中用法为下面3个步骤
注:WKCookieManager单利 在下面Demo中
1. //注入 JS 代码块,解决跨域丢失问题
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
WKUserContentController *contoller = [[WKUserContentController alloc] init];
[contolleraddUserScript:[[WKCookieManager shareManager] futhureCookieScript]];
configuration.userContentController= contoller;
2. //拼接同步到 NSHTTPCookieStorage 中的 Cookei
[self.webView loadRequest:[[WKCookieManager shareManager]cookieAppendRequest:@"http://www.baidu.com"]];
3. //防止新的跳转 cooki 丢失问题
在WKNavigationDelegate的方法中调用
[[WKCookieManager shareManager] fixNewRequestCookieWithRequest:navigationAction.request];
- (void)webView:(WKWebView*)webView decidePolicyForNavigationAction:(WKNavigationAction*)navigationAction decisionHandler:(void(^)(WKNavigationActionPolicy))decisionHandler {
[[WKCookieManager shareManager] fixNewRequestCookieWithRequest:navigationAction.request];
decisionHandler(WKNavigationActionPolicyAllow);
}
通过Charles青花瓷抓包来查看Cookie 是否设置成功。注意清除缓存
JS调用OC
//方法注入
// window.webkit.messageHandlers..postMessage() for all 前端要这样写,页面退出前需要移除
[self.webView.configuration.userContentController addScriptMessageHandler:self name:@"JSSendMessageToOC"];
- (void)viewDidDisappear:(BOOL)animated{
[superviewDidDisappear:animated];
//必须移除 否则VC不释放
[self.webView.configuration.userContentController removeScriptMessageHandlerForName:@"JSSendMessageToOC"];
}
#pragma mark - WKScriptMessageHandler
- (void)userContentController:(WKUserContentController*)userContentController didReceiveScriptMessage:(WKScriptMessage*)message{
NSLog(@"%@---%@",message.name,message.body);
// 第一个参数为f方法名(自行和前端协商格式)
NSDictionary*dic = message.body;
NSString*common_mothed = dic.allKeys.firstObject;
//注入的公共方法
if(![message.nameisEqualToString:@"JSSendMessageToOC"]) {
return;
}
if([common_mothedisEqualToString:@"XXX"]) {
}
}
OC 调用JS
- (void)ocSendMessageToJs:(NSString*)method parameter:(NSString*)para{
NSString *jsStr2 = [NSString stringWithFormat:@"%@(%@)",method,para];
[self.webView evaluateJavaScript:jsStr2 completionHandler:^(id _Nullable result, NSError * _Nullable error) {
NSLog(@"%@----%@",result, error);
}];
}
Demo 示例:
说明:
1.在ViewController中加载了一个UIWebview ,通过设置Cookie模拟登录后拿到的Cookie (真实开发中可忽略)
加载时,我通过Charles 抓包(此时还未点击登录成功设置Cookie按钮)结果如下
未点击设置Cookie2.点击了跳转WKWebView ,来看下WKWebview的Cookie
未设置WKWebview的Cookie3.然后返回,点击登录成功设置Cookie ,然后刷新UIWebVIew,通过Charles 查看UIWebView的Cookie
发现多了一个我们自己设置的TeeMo_Cookie_WebView
已经设置UIWebView的Cookie4.点击跳转WKWebView ,通过Charles 查看WKWebView的Cookie
已经设置WKWebView的Cookie此时都有Cookie了,我们返回,然后再进去,发现WKWebView的Cookie依然存在。
核心代码
/*
拼接同步到 NSHTTPCookieStorage 中的 Cookei, 第一次尝试如何让 URL 刚开始加载是带上自己的 Cookie,可以通过抓包工具查看。
@paramurl 要加载的URL
@return拼接了 Cookie 字段后的请求
*/
- (NSURLRequest*)cookieAppendRequest:(NSString*)url{
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
NSArray *cookies = [NSHTTPCookieStorage sharedHTTPCookieStorage].cookies;
//Cookies数组转换为requestHeaderFields
NSDictionary *requestHeaderFields = [NSHTTPCookie requestHeaderFieldsWithCookies:cookies];
//设置请求头
request.allHTTPHeaderFields= requestHeaderFields;
NSLog(@"%@",request.allHTTPHeaderFields);
return request;
}
/**
跨域请求丢失问题
@return注入的 JS 代码块
*/
- (WKUserScript*)futhureCookieScript{
WKUserScript * cookieScript = [[WKUserScript alloc] initWithSource:[self cookieString] injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
return cookieScript;
}
- (NSString*)cookieString
{
NSMutableString *script = [NSMutableString string];
[scriptappendString:@"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;
}
[scriptappendFormat:@"if (cookieNames.indexOf('%@') == -1) { document.cookie='%@'; };\n", cookie.name, cookie.kc_formatCookieString];
}
return script;
}
/**
解决新的跳转 Cookie 丢失问题
@paramoriginalRequest 拦截的请求
@return带上 Cookie 的请求
*/
- (NSURLRequest*)fixNewRequestCookieWithRequest:(NSURLRequest*)originalRequest{
NSMutableURLRequest *fixedRequest;
if ([originalRequest isKindOfClass:[NSMutableURLRequest class]]) {
fixedRequest = (NSMutableURLRequest*)originalRequest;
}else{
fixedRequest = originalRequest.mutableCopy;
}
NSDictionary *dict = [NSHTTPCookie requestHeaderFieldsWithCookies:[NSHTTPCookieStorage sharedHTTPCookieStorage].cookies];
if(dict.count) {
NSMutableDictionary *mDict = originalRequest.allHTTPHeaderFields.mutableCopy;
[mDictsetValuesForKeysWithDictionary:dict];
fixedRequest.allHTTPHeaderFields= mDict;
}
return fixedRequest;
}