WKWebView
本来是有设置cookie的api的,具体做法如下
// 创建一个WKUserScript,设置好cookie
WKUserScript *cookieScript = [[WKUserScript alloc] initWithSource:@"document.cookie='name=Zhang;age=28;'" injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES];
// webView 执行这个Script
[webView.configuration.userContentController addUserScript:cookieScript];
结果如何呢?等网页加载出来后,在web检查器
中看一下存储空间
:
不知道怎么打开web检查器的:首先保证你的手机开了web检查器
选项,设置
>Safari
>高级
>web检查器
,然后手机连上电脑,在电脑端的Safari选择开发
>你的手机名
>右边就是webView列表
>选择想要查看的页面
看到这里,可以看到,一条语句虽然设置两个cookie,但只有一条生效,age=18找不到。算了,没有就分开设置,一条一条设也是可以的。
正准备拍拍手,打完收工?且慢!后台有『茬』要找了,后台说,我根本没有看到cookie啊!
你说,怎么可能,苹果爸爸做的东西怎么会有问题,一定是你们的问题。
被后台『找茬』多次后,我们来抓包看看吧,还是一样的程序,还是一样的代码,结果如下
程序发出的请求中cookie列表
阿勒!仔细对比下,除了自己设置的cookie一条没有,其他的cookie一条不少。
这是为什么呢?踩了一年
WKWebView
的坑,我想我可以解释下,WKUserScript,从名字来看,这根本就不是专门设置cookie的啊,它是用来注入本地js脚本的,不只是cookie,其他的js方法啊什么的都可以用它来注入。而这个类的初始化方法中有个时间参数
WKUserScriptInjectionTime
,这是个枚举有两个值.......AtDocumentStart
和...end
,从名字中可以看出,这分别是在html的Document文档开始加载和加载结束时注入js。也就是说,这个方法设置cookie的过程是在数据已经下载完成,在本地解析过程中设置的,后台完全看不到啊。是的,后台找你那么多『茬』真的是你的错。
当初完全没想到这其中的原因,我也不知道怎么解决。那时,我也就听从了我们后台的方案:
- 在发起的request请求头里面,手动设置所有的cookie,包括自己要加的、NSHTTPCookieStorage里面本来有的,这是为了后台能拿到cookie。
- 发起request请求。
- 在收到网页数据时,把之前发送的那些cookie字符串,手动的在webview里面再执行一次,这是为了web本地能拿到cookie。
具体的代码如下
// 1. 先添加cookie到String
NSMutableString *cookieString = [NSMutableString stringWithFormat:@"name=zhang;(这里面的分号千万不要忘记)"];
// 2. 把网页本来有的cookie接上
NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:[NSURL URLWithString:URL_HOME]];
for (NSHTTPCookie *cookie in cookies) {
[cookieString appendString:[NSString stringWithFormat:@"%@=%@;(这个分号同样不能忘)", cookie.name, cookie.value]];
}
// 3. 在request里面添加上cookie
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setValue:cookieString forHTTPHeaderField:@"Cookie"];
// 4. webView 发起request请求
[_webView loadRequest:request];
// 5. 在WKWebView的代理方法didCommitNavigation里面设置cookie
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation {
// [webView setAllCookie];
[webView evaluateJavaScript:@"document.cookie = 'name=zhang';" completionHandler:nil];
}
后续的问题:这个方案执行过程中可能会遇到一些问题,当然方案本身没有问题,一定是你的问题。
-
后台只能收到部分cookie,有的cookie收不到
有次,后台问我:那个啥啥cookie你没有设置吧!其他cookie都有,就这个收不到。我:不可能吧,我看我代码里把所有cookie都设了啊,我不管了。于是后台去排查了半天,发现,一串cookie字符串的末尾,少了个分号;
。。。
🤣没错,是我的问题,在步骤1里我的cookieString大概是这样的@"c1=v1;c2=v2;......;name=aaa",aaa后面的;
呢??大概被我吃了吧。 -
后台没有收到任何cookie,也就是这个方法似乎无效
这个问题有个读者也问过我,我也不知道什么情况,也没给他解决。
而那天我似乎遇到了同样的情况,大概是这样的,在一个列表里选择item
>item选择完毕,表示待会要设置新cookie
>回到webView的页面
>webView刷新
>结果,抓包显示后台没有收到cookie。
仔细看看这个流程,webView加载数据的过程中只做了一个操作,刷新。那么就真相大白了,刷新操作并不经过重新拼接cookie,不经过生成新的request请求过程,因此也就根本没有发送cookie。
正确的做法,凡是要设置新的cookie,从后台拿新数据,那么,不要刷新,重新拼接cookie字符串,重新loadRequest吧。
网友评论