Cookie简介说到Cookie,或许有些小伙伴会比较陌生,有些小伙伴会比较熟悉。如果项目中,所有页面都是纯原生来实现的话,一般Cookie这个东西或许我们永远也不会接触到。但是,这里还是要说一下Cookie,因为它真的很重要,由它产生的一些坑也很多。
Cookie 在 web中应用比较多,主要是记录一个状态,比如我在网页上登录了,我就可以拿到网页登录后 Cookie,下次再 Cookie 的生效期内我就可以不用输入账号密码,直接跳转登录状态,在App中,Cookie最常用的也就是维持登录状态了.因为笔者最近就在做这个,其中也遇到过很多坑,这里说先踩坑和用法
iOS Cookie 的管理
NSHTTPCookie和NSHTTPCookieStorageiOS中进行HTTP网络请求Cookie管理主要由两个类负责,一个类是NSHTTPCookieStorage类,一个是NSHTTPCookie类。
NSHTTPCookieStorage
NSHTTPCookieStorage类采用单例的设计模式,其中管理着所有HTTP请求的Cookie信息官方解释:NSHTTPCookieStorage 是一个用来管理 cookie 存储的单例。一个 [NSHTTPCookie](https://link.jianshu.com?t=https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSHTTPCookie_Class/index.html#//apple_ref/occ/cl/NSHTTPCookie) 单例代表一个 cookie。通常来讲,cookie 可以在应用间共享,并且在进程之间保持同步。 对于单进程,Session cookies (这里的 cookie 对象的 [isSessionOnly](https://link.jianshu.com?t=https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSHTTPCookie_Class/index.html#//apple_ref/occ/instm/NSHTTPCookie/isSessionOnly) 方法返回 `YES`)是局部的并且不能被共享。
**常用方法**// 获取单例对象+ (NSHTTPCookieStorage *)sharedHTTPCookieStorage;
// 所有Cookie数据数组 其中存放NSHTTPCookie对象@property (nullable , readonly, copy) NSArray<NSHTTPCookie *> *cookies;
// 手动设置一条Cookie数据- (void)setCookie:(NSHTTPCookie *)cookie;
// 删除某条Cookie信息- (void)deleteCookie:(NSHTTPCookie *)cookie;
// 删除某个时间后的所有Cookie信息 iOS8后可用- (void)removeCookiesSinceDate:(NSDate *)date NS_AVAILABLE(10_10, 8_0);
// 获取某个特定URL的所有Cookie数据- (nullable NSArray<NSHTTPCookie *> *)cookiesForURL:(NSURL *)URL;
// 为某个特定的URL设置Cookie- (void)setCookies:(NSArray<NSHTTPCookie *> *)cookies forURL:(nullable NSURL *)URL mainDocumentURL:(nullable NSURL *)mainDocumentURL;
// Cookie数据的接收协议枚举如下:typedef NS_ENUM(NSUInteger, NSHTTPCookieAcceptPolicy) { NSHTTPCookieAcceptPolicyAlways,//接收所有Cookie信息 NSHTTPCookieAcceptPolicyNever,//不接收所有Cookie信息 NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain//只接收主文档域的Cookie信息};@property NSHTTPCookieAcceptPolicy cookieAcceptPolicy;
系统下面的两个通知与Cookie管理有关:据说,在Mac OS是cookie可以共享的(Session cookies 不能共享),在Mac OS app中更改cookie的接收策略会影响到其他正在运行的在使用cookie storage的app.这时NSHTTPCookieStorage会发出两个通知:// Cookie数据的接收协议改变时发送的通知FOUNDATION_EXPORT NSString * const NSHTTPCookieManagerAcceptPolicyChangedNotification;// 管理的Cookie数据发生变化时发送的通知FOUNDATION_EXPORT NSString * const NSHTTPCookieManagerCookiesChangedNotification;
```**NSHTTPCookie介绍**> NSHTTPCookie是具体的HTTP请求Cookie数据对象.
```// 下面两个方法用于对象的创建和初始化 都是通过字典进行键值设置- (nullable instancetype)initWithProperties:(NSDictionary<NSString *, id> *)properties;+ (nullable NSHTTPCookie *)cookieWithProperties:(NSDictionary<NSString *, id> *)properties;
// 返回Cookie数据中可用于添加HTTP头字段的字典+ (NSDictionary<NSString *, NSString *> *)requestHeaderFieldsWithCookies:(NSArray<NSHTTPCookie *> *)cookies;
// 从指定的响应头和URL地址中解析出Cookie数据+ (NSArray<NSHTTPCookie *> *)cookiesWithResponseHeaderFields:(NSDictionary<NSString *, NSString *> *)headerFields forURL:(NSURL *)URL;
// Cookie数据中的属性字典@property (nullable, readonly, copy) NSDictionary<NSString *, id> *properties;
// 请求响应的版本@property (readonly) NSUInteger version;
// 请求相应的名称@property (readonly, copy) NSString *name;
// 请求相应的值@property (readonly, copy) NSString *value;
// 过期时间@property (nullable, readonly, copy) NSDate *expiresDate;
// 请求的域名@property (readonly, copy) NSString *domain;
//请求的路径@property (readonly, copy) NSString *path;
// 是否是安全传输@property (readonly, getter=isSecure) BOOL secure;
// 是否只发送HTTP的服务@property (readonly, getter=isHTTPOnly) BOOL HTTPOnly;
// 响应的文档@property (nullable, readonly, copy) NSString *comment;
// 相应的文档URL@property (nullable, readonly, copy) NSURL *commentURL;
// 服务端口列表@property (nullable, readonly, copy) NSArray<NSNumber *> *portList;
```**HTTP cookie的属性键**属性 |解读- | :-: |NSHTTPCookieName | Cookie的名字NSHTTPCookieValue | Cookie的值NSHTTPCookieOriginURL | 和域名一样,NSHTTPCookieDomain或NSHTTPCookieOriginURL必须指定一个值NSHTTPCookieVersion | 接收器的版本NSHTTPCookieDomain | 域名NSHTTPCookiePath | Cookie 存放路径NSHTTPCookieSecure | Cookie是否只应通过安全通道发送,设置Cookie的secure属性为true。只会在HTTPS和SSL等安全协议中传输此类Cookie。默认为falseNSHTTPCookieComment | 包含Cookie的评论,只有有效的版本1的cookies或更高版本。 这头字段是可选的NSHTTPCookieCommentURL | 接收器的评论URLNSHTTPCookieDiscard | Cookie是否应在会议结束时丢弃NSString,字符串值必须是“true”或“假”。 这个字段是可选的。 默认为“假”,除非这是Cookie是第1版或以上,NSHTTPCookieMaximumAge未指定,在这种情况下,它被假定为“TRUE”NSHTTPCookieMaximumAge | NSString对象,包含一个整数,在Cookie内保持最多几秒 。仅适用于第1版和更高版本的有效。 默认为“0”。 此字段是可选的NSHTTPCookiePort | 接收机的端口
* **UIWebView的 Cookie 机制**> UIWebView 在浏览网页后会将网页中的 cookie 自动存入 NSHTTPCookieStorage 标准容器中,[NSHTTPCookieStorage sharedHTTPCookieStorage]这个单例管理,在后续访问中会将 cookie 自动带到 request 请求当中。并且在同一个app内多个UIWebView之间共享。
* webView 中获取 cookie```//加载成功- (void)webViewDidFinishLoad:(UIWebView *)webView { NSString *requestUrl = webView.request.URL.absoluteString; NSLog(@" requestUrl: %@",requestUrl);
//设置原始 cookie 根据key 存储本地 NSMutableArray *cookieArray = [[NSMutableArray alloc] init];
//网页加载完成取出 cookies NSArray *nCookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]; NSHTTPCookie *cookie; for (id c in nCookies) { if ([c isKindOfClass:[NSHTTPCookie class]]) { cookie=(NSHTTPCookie *)c; //我这里是cookie存入字典中 去重 if ([cookie value]) { //如果 vaule 值不为 nil 存入字典中, [self.mutableDic setValue:[cookie value] forKey:[cookie name]]; }//设置原始 cookie NSMutableDictionary *cookieProperties = [NSMutableDictionary dictionary]; [cookieProperties setObject:cookie.name forKey:NSHTTPCookieName]; [cookieProperties setObject:cookie.value forKey:NSHTTPCookieValue]; [cookieProperties setObject:cookie.domain forKey:NSHTTPCookieDomain]; [cookieProperties setObject:cookie.path forKey:NSHTTPCookiePath]; [cookieProperties setObject:[[NSDate date] dateByAddingTimeInterval:2629743] forKey:NSHTTPCookieExpires]; [cookieArray addObject:cookieProperties];
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie]; } }//cookie 存入本地 [[NSUserDefaults standardUserDefaults] setObject:cookieArray forKey:@"cookieArray"]; [[NSUserDefaults standardUserDefaults] synchronize];
//下面 cookie 去重是为了得到 key=Value;形式的字符串,这里由于我有需求这样做,实际中下面可以忽略 NSMutableString *cookieValue = [NSMutableString stringWithFormat:@""]; // cookie重复,先放到字典进行去重,再进行拼接 for (NSString *key in self.mutableDic) { NSString *appendString = [NSString stringWithFormat:@"%@=%@;", key, [self.mutableDic valueForKey:key]]; [cookieValue appendString:appendString]; }NSLog(@"######################## %@ ####################",cookieValue);```
* 设置 cookie``` NSMutableArray* cookieDictionary = [[NSUserDefaults standardUserDefaults] valueForKey:@"cookieArray"]; NSLog(@"cookie dictionary found is %@",cookieDictionary); if (cookieDictionary) { for (NSInteger i = 0; i < cookieDictionary.count; i++) { NSLog(@"cookie found is %@",[cookieDictionary objectAtIndex:i]); NSDictionary *cookieDic = [cookieDictionary objectAtIndex:i]; NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:cookieDic]; [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie]; } } //设置请求之前加载 cookie 确保 cookie 在请求头之前设置 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:self.URLString] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];
//加载网页 [self.webView loadRequest:request];
```* 删除 cookie```// 清空 cookie- (void)deleteCookie { // 清空 cookie NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage]; NSArray *_tmpArray = [NSArray arrayWithArray:[cookieJar cookies]]; for (id obj in _tmpArray) { [cookieJar deleteCookie:obj]; }}```
* **WKWebView 的 Cookie 机制**> NSURLCache和NSHTTPCookieStroage无法操作(WKWebView)WebCore进程的缓存和CookieWKWebView实例将会忽略任何的默认网络存储器(NSURLCache, NSHTTPCookieStorage, NSCredentialStorage) 和一些标准的自定义网络请求类(NSURLProtocol,等等.),WKWebView实例不会把Cookie存入到App标准的的Cookie容器(NSHTTPCookieStorage)中,因为 NSURLSession/NSURLConnection等网络请求使用NSHTTPCookieStorage进行访问Cookie,所以不能访问WKWebView的Cookie,现象就是WKWebView存了Cookie,其他的网络类如NSURLSession/NSURLConnection却看不到。这是很多人的说法。还有一种是说法是通过实践发现 WKWebView 实例其实也会将 Cookie 存储于 NSHTTPCookieStorage 中,但存储时机有延迟,因为WKWebView内也有cookie的容器,而且每隔一段时间就和app侧NSHTTPCookieStorage进行同步,而且这个同步是进程级别的同步,而且这个同步是单向。至于以上两种说法,最终WKWebView Cookie 问题在于 WKWebView 发起的请求不会自动带上存储于 NSHTTPCookieStorage 容器中的 Cookie。
* **iOS11**iOS11 的 API 可以解决该问题,只要是存在 WKHTTPCookieStore 里的 cookie,WKWebView 每次请求都会携带,存在 NSHTTPCookieStorage 的cookie,并不会每次都携带。于是会发生首次 WKWebView 请求不携带 Cookie 的问题。
* **ios 11 WKWebView cookie 的注入**在执行 -[WKWebView loadReques:] 前将 NSHTTPCookieStorage 中的内容复制到 WKHTTPCookieStore 中,以此来达到 WKWebView Cookie 注入的目的。示例代码如下:```[self copyNSHTTPCookieStorageToWKHTTPCookieStoreWithCompletionHandler:^{ NSURL *url = [NSURL URLWithString:@"https://www.v2ex.com"]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; [_webView loadRequest:request]; }];
```
```- (void)copyNSHTTPCookieStorageToWKHTTPCookieStoreWithCompletionHandler:(nullable void (^)())theCompletionHandler; { NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]; WKHTTPCookieStore *cookieStroe = self.webView.configuration.websiteDataStore.httpCookieStore; if (cookies.count == 0) { !theCompletionHandler ?: theCompletionHandler(); return; } for (NSHTTPCookie *cookie in cookies) { [cookieStroe setCookie:cookie completionHandler:^{ if ([[cookies lastObject] isEqual:cookie]) { !theCompletionHandler ?: theCompletionHandler(); return; } }]; }}
```
* **ios11 之前**注入 Cookie 就是从之前保存 cookie 的 NSHTTPCookieStorage 中取出相关 Cookie,然后在再次请求访问的时候在 request 中注入 Cookie。注入Cookie同样有多种方式。
* **1.JS注入1**```//取出 storage 中的cookie并将其拼接成正确的形式NSArray<NSHTTPCookie *> *tmp = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]; NSMutableString *jscode_Cookie = [@"" mutableCopy]; [tmp enumerateObjectsUsingBlock:^(NSHTTPCookie * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { NSLog(@"%@ = %@", obj.name, obj.value); [jscode_Cookie appendString:[NSString stringWithFormat:@"document.cookie = '%@=%@';", obj.name, obj.value]]; }];
WKUserContentController* userContentController = WKUserContentController.new; WKUserScript * cookieScript = [[WKUserScript alloc] initWithSource: @"" injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO]; [userContentController addUserScript:cookieScript]; WKWebViewConfiguration* webViewConfig = WKWebViewConfiguration.new; webViewConfig.userContentController = userContentController;WKWebView * webView = [[WKWebView alloc] initWithFrame:CGRectMake(/*set your values*/) configuration:webViewConfig];```* **JS注入2**```- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation { [webView evaluateJavaScript:@"document.cookie ='TeskCookieKey1=TeskCookieValue1';" completionHandler:^(id result, NSError *error) { //... }];}
```* **NSMutableURLRequest 注入Cookie**```NSURL *url = request.URL;NSMutableString *cookies = [NSMutableString string];NSMutableURLRequest *requestObj = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];NSArray *tmp = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];NSDictionary *dicCookies = [NSHTTPCookie requestHeaderFieldsWithCookies:tmp];NSString *cookie = [self readCurrentCookie];[requestObj setValue:cookie forHTTPHeaderField:@"Cookie"];[_webView loadRequest:requestObj];
-(NSString *)readCurrentCookie{ NSMutableDictionary *cookieDic = [NSMutableDictionary dictionary]; NSMutableString *cookieValue = [NSMutableString stringWithFormat:@""]; NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage]; for (NSHTTPCookie *cookie in [cookieJar cookies]) { [cookieDic setObject:cookie.value forKey:cookie.name]; } // cookie重复,先放到字典进行去重,再进行拼接 for (NSString *key in cookieDic) { NSString *appendString = [NSString stringWithFormat:@"%@=%@;", key, [cookieDic valueForKey:key]]; [cookieValue appendString:appendString]; } return cookieValue;}
```**获取Cookie**由于 WKWebView 的 Cookie 存储容器 WKWebsiteDataStore 是私有存储,所以无法从这里获取到Cookie,目前的方法是(1)从网站返回的 response headerfields 中获取。(2)通过调用js的方法获取 cookie。
* **1.从网站返回的 response headerfields 中获取,因为cookie都存在http respone的headerfields,找到能获得respone的WKWebView回调,打印**```- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{ NSHTTPURLResponse *response = (NSHTTPURLResponse *)navigationResponse.response; NSArray *cookies =[NSHTTPCookie cookiesWithResponseHeaderFields:[response allHeaderFields] forURL:response.URL]; //读取wkwebview中的cookie 方法1 for (NSHTTPCookie *cookie in cookies) {// [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie]; NSLog(@"wkwebview中的cookie:%@", cookie); } //读取wkwebview中的cookie 方法2 读取Set-Cookie字段 NSString *cookieString = [[response allHeaderFields] valueForKey:@"Set-Cookie"]; NSLog(@"wkwebview中的cookie:%@", cookieString); //看看存入到了NSHTTPCookieStorage了没有 NSHTTPCookieStorage *cookieJar2 = [NSHTTPCookieStorage sharedHTTPCookieStorage]; for (NSHTTPCookie *cookie in cookieJar2.cookies) { NSLog(@"NSHTTPCookieStorage中的cookie%@", cookie); }//下面是将 原始cookie本地 化NSMutableArray *cookieArray = [[NSMutableArray alloc] init]; for (NSHTTPCookie *cookie in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]) {
NSMutableDictionary *cookieProperties = [NSMutableDictionary dictionary]; [cookieProperties setObject:cookie.name forKey:NSHTTPCookieName]; [cookieProperties setObject:cookie.value forKey:NSHTTPCookieValue]; [cookieProperties setObject:cookie.domain forKey:NSHTTPCookieDomain]; [cookieProperties setObject:cookie.path forKey:NSHTTPCookiePath]; [cookieProperties setObject:[NSNumber numberWithInt:cookie.version] forKey:NSHTTPCookieVersion]; [cookieProperties setObject:[[NSDate date] dateByAddingTimeInterval:2629743] forKey:NSHTTPCookieExpires]; [cookieArray addObject:cookieProperties]; } [[NSUserDefaults standardUserDefaults] setValue:cookieArray forKey:@"cookieArray"]; [[NSUserDefaults standardUserDefaults] synchronize];
decisionHandler(WKNavigationResponsePolicyAllow);}
// 页面加载完成之后调用需要重新给WKWebView设置Cookie防止因为a标签跳转,导致下一次跳转的时候Cookie丢失。- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{ //取出cookie NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage]; //js函数 NSString *JSFuncString = @"function setCookie(name,value,expires)\ {\ var oDate=new Date();\ oDate.setDate(oDate.getDate()+expires);\ document.cookie=name+'='+value+';expires='+oDate+';path=/'\ }\ function getCookie(name)\ {\ var arr = document.cookie.match(new RegExp('(^| )'+name+'=({FNXX==XXFN}*)(;|$)'));\ if(arr != null) return unescape(arr[2]); return null;\ }\ function delCookie(name)\ {\ var exp = new Date();\ exp.setTime(exp.getTime() - 1);\ var cval=getCookie(name);\ if(cval!=null) document.cookie= name + '='+cval+';expires='+exp.toGMTString();\ }";
//拼凑js字符串 NSMutableString *JSCookieString = JSFuncString.mutableCopy; for (NSHTTPCookie *cookie in cookieStorage.cookies) { NSString *excuteJSString = [NSString stringWithFormat:@"setCookie('%@', '%@', 1);", cookie.name, cookie.value]; [JSCookieString appendString:excuteJSString]; } //执行js [webView evaluateJavaScript:JSCookieString completionHandler:^(id obj, NSError * _Nullable error) { NSLog(@"%@",error); }];}
```* 通过 JS 获取 cookie```- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation{ [webView evaluateJavaScript:[NSString stringWithFormat:@"document.cookie"] completionHandler:^(id _Nullable response, NSError * _Nullable error) { if (response != 0) { NSLog(@"\n\n\n\n\n\n document.cookie%@,%@",response,error); } }];}```##注意document.cookie 的方法获取 cookie并不支持跨越获取,如果设置 httponly则获取不到 cookie不论是(1)还是(2)方法,似乎都无法解决302请求的 Cookie 问题。举例来说,假设你要访问网站A,在A中点击登录,跳转页面到B地址,在B中完成登录之后302跳转回A网站。此时cookie是存在于B地址的 response 中的,在A地址的 response 中并没有 cookie 的字段。然而我们只能获取到A地址的 response ,无法截获到B地址的response。因此获取不到该类型网站的 cookie 。由于我并没有遇到302这样的问题,所有看了下网上的资料,希望对遇到这个问题的小伙伴一下办法,网上给出的解决办法是: * 1.加载一个本地为空的html,域名指向你的第一次加载的url的域名。```//加载本地html[self.webView loadHTMLString:@"" baseURL:[NSURL URLWithString:@"https:/a.com"]];```* 2.通过以下方法,在第一次加载完成后,将需要设置的Cookies设置到WKWebView中,因为是加载的本地的html以下方法会立即执行。```// 页面加载完成之后调用- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{ if (isFirstLoaded) { NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage]; //js函数 NSString *JSFuncString = @"function setCookie(name,value,expires)\ {\ var oDate=new Date();\ oDate.setDate(oDate.getDate()+expires);\ document.cookie=name+'='+value+';expires='+oDate+';path=/'\ }"; //拼凑js字符串,按照自己的需求拼凑Cookie NSMutableString *JSCookieString = JSFuncString.mutableCopy; for (NSHTTPCookie *cookie in cookieStorage.cookies) { if (![cookie.name isEqualToString:@"__cust"]) { NSString *excuteJSString = [NSString stringWithFormat:@"setCookie('%@', '%@', 3);", cookie.name, cookie.value]; [JSCookieString appendString:excuteJSString]; } } //执行js [webView evaluateJavaScript:JSCookieString completionHandler:^(id obj, NSError * _Nullable error) { //加载真正的第一次Request [self loadRealRequest]; }]; }}
```
**如果cookie 存储到本地获取本地的 cookie**```//修改从 storage 中读取 cookie 的方法-(NSString *)readCurrentCookie{ NSMutableArray* cookieDictionary = [[NSUserDefaults standardUserDefaults] valueForKey:@"cookieArray"]; NSLog(@"cookie dictionary found is %@",cookieDictionary); for (int i=0; i < cookieDictionary.count; i++) { NSLog(@"cookie found is %@",[cookieDictionary objectAtIndex:i]); NSMutableDictionary* cookieDictionary1 = [[NSUserDefaults standardUserDefaults] valueForKey:[cookieDictionary objectAtIndex:i]]; NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:cookieDictionary1]; [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie]; } NSMutableDictionary *cookieDic = [NSMutableDictionary dictionary]; NSMutableString *cookieValue = [NSMutableString stringWithFormat:@""]; NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage]; for (NSHTTPCookie *cookie in [cookieJar cookies]) { [cookieDic setObject:cookie.value forKey:cookie.name]; } // cookie重复,先放到字典进行去重,再进行拼接 for (NSString *key in cookieDic) { NSString *appendString = [NSString stringWithFormat:@"%@=%@;", key, [cookieDic valueForKey:key]]; [cookieValue appendString:appendString]; } return cookieValue;}
```
**清除 cookie**```#pragma mark - 清空cookie-(void)deleCookie {// NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage];// NSArray *_tmpArray = [NSArray arrayWithArray:[cookieJar cookies]];// for (id obj in _tmpArray) {// [cookieJar deleteCookie:obj];// } if (@available(iOS 9.0, *)) {//iOS9及以上 WKWebsiteDataStore *dateStore = [WKWebsiteDataStore defaultDataStore]; [dateStore fetchDataRecordsOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] completionHandler:^(NSArray<WKWebsiteDataRecord *> * __nonnull records) { for (WKWebsiteDataRecord *record in records) { //if ( [record.displayName containsString:@"baidu"]) //取消备注,可以针对某域名做专门的清除,否则是全部清除 // { [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:record.dataTypes forDataRecords:@[record] completionHandler:^{ NSLog(@"Cookies for %@ deleted successfully",record.displayName); }]; // } } }]; }else { //iOS9以下 NSString *libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0]; NSString *cookiesFolderPath = [libraryPath stringByAppendingString:@"/Cookies"]; NSError *errors; [[NSFileManager defaultManager] removeItemAtPath:cookiesFolderPath error:&errors]; }}
```##最后UIWebView 和 WKWebView 所遇到问题 cookie 同步,获取,删除,设置这些问题,目前就这么多解决办法吧,我一开始尝试用 WKWebView 获取 cookie 但是最后遇到网页跨域问题以及低版本兼容问题我还是换回 UIWebView 了,如果有更好的解决办法可以在下面留言,谢谢!
转载于:https://www.cnblogs.com/ningmengcao-ios/p/9578218.html