###1、同步cookie 工具类
@interface WKCookieSyncManager : NSObject
@property (nonatomic, strong) WKProcessPool *processPool;
@property (nonatomic, assign) BOOL loginCookieHasBeenSynced;
+ (instancetype)sharedWKCookieSyncManager;
+ (NSMutableArray<NSString *> *)cookieJavaScriptArray;
- (void)setCookies:(NSArray<NSHTTPCookie *> *)cookies forDomain:(NSString *)domain;
- (NSArray<NSHTTPCookie *> *)cookies;
- (void)removeCookies;
- (void)cookiesSyncForWebsiteDataStore:(void(^)(WKWebsiteDataStore *dataStore))completion;
+ (void)syncCookieFromWebView:(WKWebView *)webView navigationResponse:(WKNavigationResponse *)navigationResponse;
@end
复制代码
WKCookieSyncManager implementation
@interface WKCookieSyncManager () <WKNavigationDelegate>
@property (nonatomic, copy) NSString *domain;
@property (nonatomic, strong) dispatch_group_t cookieSyncGroup;
@end
@implementation WKCookieSyncManager
+ (instancetype)sharedWKCookieSyncManager {
static WKCookieSyncManager *sharedWKCookieSyncManagerInstance = nil;
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
sharedWKCookieSyncManagerInstance = [[self alloc] init];
});
return sharedWKCookieSyncManagerInstance;
}
- (WKProcessPool *)processPool {
if (!_processPool) {
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
_processPool = [[WKProcessPool alloc] init];
});
}
return _processPool;
}
- (instancetype)init {
self = [super init];
if (self) {
_domain = @"your domain";
_cookieSyncGroup = dispatch_group_create();
}
return self;
}
+ (NSMutableArray<NSString *> *)cookieJavaScriptArray {
NSMutableArray<NSString *> *cookieStrings = [[NSMutableArray alloc] init];
NSArray *cookies = [[WKCookieSyncManager sharedWKCookieSyncManager] cookies];
for (NSHTTPCookie *cookie in cookies) {
NSString *excuteJSString = [NSString stringWithFormat:@"%@=%@;", cookie.name, cookie.value];
if (cookie.domain.length > 0) {
excuteJSString = [excuteJSString stringByAppendingFormat:@"domain=%@;", cookie.domain];
}
if (cookie.path.length > 0) {
excuteJSString = [excuteJSString stringByAppendingFormat:@"path=%@;", cookie.path];
}
if (cookie.expiresDate != nil) {
excuteJSString = [excuteJSString stringByAppendingFormat:@"expires=%@;", cookie.expiresDate];
}
if (cookie.secure) {
excuteJSString = [excuteJSString stringByAppendingString:@"secure=true"];
}
[cookieStrings addObject:excuteJSString];
NSLog(@"cookie to be set = %@", excuteJSString);
}
// 检查cookie的数量,正常的应该是 7 个
NSLog(@"cookieJavaScriptArray.cookie.length = %ld", cookieStrings.count);
return cookieStrings;
}
- (void)setCookies:(NSArray<NSHTTPCookie *> *)cookies forDomain:(NSString *)domain {
if (![domain containsString:self.domain]) {
return;
}
NSData *cookieData = [NSKeyedArchiver archivedDataWithRootObject:cookies];
[[NSUserDefaults standardUserDefaults] setObject:cookieData forKey:self.domain];
[[NSUserDefaults standardUserDefaults] synchronize];
self.loginCookieHasBeenSynced = YES;
}
- (NSArray<NSHTTPCookie *> *)cookies {
NSData *cookieData = [[NSUserDefaults standardUserDefaults] objectForKey:self.domain];
if (!cookieData) {
return nil;
}
NSArray *cookies = [NSKeyedUnarchiver unarchiveObjectWithData:cookieData];
for (NSHTTPCookie *cookie in cookies) {
NSLog(@"cookie== %@",cookie);
}
return cookies;
}
- (void)removeCookies {
[[NSUserDefaults standardUserDefaults] removeObjectForKey:self.domain];
[[NSUserDefaults standardUserDefaults] synchronize];
self.loginCookieHasBeenSynced = NO;
}
- (void)cookiesSyncForWebsiteDataStore:(void(^)(WKWebsiteDataStore *dataStore))completion {
NSArray<NSHTTPCookie *> *cookes = [self cookies];
if (!cookes || cookes.count == 0) {
return completion(nil);
}
if (@available(iOS 11.0, *)) {
WKWebsiteDataStore *dataStore = [WKWebsiteDataStore nonPersistentDataStore];
[cookes enumerateObjectsUsingBlock:^(NSHTTPCookie *cookie, NSUInteger idx, BOOL *stop) {
NSLog(@"cookie == %@", cookie);
dispatch_group_enter(self.cookieSyncGroup);
[dataStore.httpCookieStore setCookie:cookie completionHandler:^{
dispatch_group_leave(self.cookieSyncGroup);
}];
}];
dispatch_group_notify(self.cookieSyncGroup, dispatch_get_main_queue(), ^{
completion(dataStore);
});
return;
}
completion(nil);
}
+ (void)syncCookieFromWebView:(WKWebView *)webView
navigationResponse:(WKNavigationResponse *)navigationResponse {
if (@available(iOS 11.0, *)) {
WKHTTPCookieStore *cookieStore = webView.configuration.websiteDataStore.httpCookieStore;
[cookieStore getAllCookies:^(NSArray* cookies) {
if (cookies.count == 0) {
return ;
}
NSUInteger index = [cookies indexOfObjectPassingTest:^BOOL(NSHTTPCookie *cookie, NSUInteger idx, BOOL * _Nonnull stop) {
return [cookie.name isEqualToString:[WKCookieSyncManager sharedWKCookieSyncManager].domain];
}];
if (index == NSNotFound) {
return;
}
NSHTTPURLResponse *response = (NSHTTPURLResponse *)navigationResponse.response;
NSString *host = response.URL.host;
if (![[WKCookieSyncManager sharedWKCookieSyncManager] loginCookieHasBeenSynced]) {
[[WKCookieSyncManager sharedWKCookieSyncManager] setCookies:cookies forDomain:host];
}
}];
return;
}
NSHTTPURLResponse *response = (NSHTTPURLResponse *)navigationResponse.response;
NSDictionary *allHeaderFields = [response allHeaderFields];
NSString *cookiesString = [allHeaderFields valueForKey:@"Set-Cookie"];
NSLog(@"response.URL Set-Cookie:%@", cookiesString);
NSArray *cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:allHeaderFields forURL:response.URL];
NSUInteger index = [cookies indexOfObjectPassingTest:^BOOL(NSHTTPCookie *cookie, NSUInteger idx, BOOL * _Nonnull stop) {
return [cookie.name isEqualToString:[WKCookieSyncManager sharedWKCookieSyncManager].domain];
}];
if (index != NSNotFound) {
NSString *host = response.URL.host;
if (![[WKCookieSyncManager sharedWKCookieSyncManager] loginCookieHasBeenSynced]) {
[[WKCookieSyncManager sharedWKCookieSyncManager] setCookies:cookies forDomain:host];
}
}
}
@end
复制代码
###2、通过- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
获取WKWebView cookies ,使用工具类保存起来
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler {
dispatch_async(dispatch_get_main_queue(), ^{
[WKCookieSyncManager syncCookieFromWebView:webView navigationResponse:navigationResponse];
});
decisionHandler(WKNavigationResponsePolicyAllow);
}
复制代码
3、首次打开应用,初始化WKWebView 设置已保存的Cookies,同步cookie登录态
WKCookieSyncManager *cookiesManager = [WKCookieSyncManager sharedWKCookieSyncManager];
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
// 解决 webview之间的cookie同步问题,
config.processPool = cookiesManager.processPool;
config.allowsInlineMediaPlayback = YES;
if (@available(iOS 11.0, *)) {
NSArray<NSHTTPCookie *> *cookes = [[WKCookieSyncManager sharedWKCookieSyncManager] cookies];
[cookes enumerateObjectsUsingBlock:^(NSHTTPCookie *cookie, NSUInteger idx, BOOL * _Nonnull stop) {
[config.websiteDataStore.httpCookieStore setCookie:cookie completionHandler:nil];
}];
} else {
NSMutableArray<NSString *> *oldCookies = [WKCookieSyncManager cookieJavaScriptArray];
[oldCookies enumerateObjectsUsingBlock:^(NSString *_Nonnull obj, NSUInteger idx, BOOL *_Nonnull stop) {
NSString *setCookie = [NSString stringWithFormat:@"document.cookie='%@';", obj];
WKUserScript *cookieScript = [[WKUserScript alloc] initWithSource:setCookie injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES];
[config.userContentController addUserScript:cookieScript];
}];
}
WKWebView *webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config];
self.webView = webView;
self.webView.backgroundColor = [UIColor whiteColor];
self.webView.scrollView.backgroundColor = [UIColor whiteColor];
self.webView.translatesAutoresizingMaskIntoConstraints = NO;
self.webView.scrollView.bounces = NO;
self.webView.UIDelegate = self;
[self.view addSubview:self.webView];
复制代码
###4、- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation
获取cookie string
- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation {
[self.webView evaluateJavaScript:@"document.cookie" completionHandler:^(id _Nullable cookie, NSError * _Nullable error) {
NSLog(@"调用异步获取cookie:%@", cookie);
}];
}
复制代码