iOS UIWebView 和 WKWebView 的 cookie 获取,设置,删除

Cookie简介

说到Cookie,或许有些小伙伴会比较陌生,有些小伙伴会比较熟悉。如果项目中,所有页面都是纯原生来实现的话,一般Cookie这个东西或许我们永远也不会接触到。但是,这里还是要说一下Cookie,因为它真的很重要,由它产生的一些坑也很多。

Cookie 在 web中应用比较多,主要是记录一个状态,比如我在网页上登录了,我就可以拿到网页登录后 Cookie,下次再 Cookie 的生效期内我就可以不用输入账号密码,直接跳转登录状态,在App中,Cookie最常用的也就是维持登录状态了.因为笔者最近就在做这个,其中也遇到过很多坑,这里说先踩坑和用法

iOS Cookie 的管理

  • NSHTTPCookie和NSHTTPCookieStorage

iOS中进行HTTP网络请求Cookie管理主要由两个类负责,一个类是NSHTTPCookieStorage类,一个是NSHTTPCookie类。

NSHTTPCookieStorage

NSHTTPCookieStorage类采用单例的设计模式,其中管理着所有HTTP请求的Cookie信息
官方解释:NSHTTPCookieStorage 是一个用来管理 cookie 存储的单例。一个 NSHTTPCookie 单例代表一个 cookie。通常来讲,cookie 可以在应用间共享,并且在进程之间保持同步。 对于单进程,Session cookies (这里的 cookie 对象的 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。默认为false
NSHTTPCookieComment 包含Cookie的评论,只有有效的版本1的cookies或更高版本。 这头字段是可选的
NSHTTPCookieCommentURL 接收器的评论URL
NSHTTPCookieDiscard 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进程的缓存和Cookie
WKWebView实例将会忽略任何的默认网络存储器(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.jianshu.com/p/4ae4fd25a4b8

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,688评论 1 330
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,559评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,749评论 0 226
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,581评论 0 191
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,741评论 3 271
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,684评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,122评论 2 292
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,847评论 0 182
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,441评论 0 228
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,939评论 2 232
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,333评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,783评论 2 236
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,275评论 3 220
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,830评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,444评论 0 180
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,553评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,618评论 2 249

推荐阅读更多精彩内容