经过几天的研究和实验,我找到了在 WKWebView 中管理会话的解决方案,这是一个变通方法,因为我没有找到任何其他方法来实现这一点,以下是步骤:
首先,您需要创建方法来设置和获取用户默认值中的数据,当我说数据时,它表示 NSData,这里是方法。
+(void)saveDataInNSDefault:(id)object key:(NSString *)key{
NSData *encodedObject = [NSKeyedArchiver archivedDataWithRootObject:object];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:encodedObject forKey:key];
[defaults synchronize];
}
+ (id)getDataFromNSDefaultWithKey:(NSString *)key{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSData *encodedObject = [defaults objectForKey:key];
id object = [NSKeyedUnarchiver unarchiveObjectWithData:encodedObject];
return object;
}
为了维护 webview 上的会话,我将 webview 和 WKProcessPool 设为单例。
- (WKWebView *)sharedWebView {
static WKWebView *singleton;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
WKWebViewConfiguration *webViewConfig = [[WKWebViewConfiguration alloc] init];
WKUserContentController *controller = [[WKUserContentController alloc] init];
[controller addScriptMessageHandler:self name:@"callNativeAction"];
[controller addScriptMessageHandler:self name:@"callNativeActionWithArgs"];
webViewConfig.userContentController = controller;
webViewConfig.processPool = [self sharedWebViewPool];
singleton = [[WKWebView alloc] initWithFrame:self.vwContentView.frame configuration:webViewConfig];
});
return singleton;
}
- (WKProcessPool *)sharedWebViewPool {
static WKProcessPool *pool;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
pool = [Helper getDataFromNSDefaultWithKey:@"pool"];
if (!pool) {
pool = [[WKProcessPool alloc] init];
}
});
return pool;
}
在 ViewDidLoad 中,我检查它是否不是登录页面,并从 User Defaults 将 cookie 加载到 HttpCookieStore 中,这样它将通过身份验证或使用这些 cookie 来维护会话。
if (!isLoginPage) {
[request setValue:accessToken forHTTPHeaderField:@"Authorization"];
NSMutableSet *setOfCookies = [Helper getDataFromNSDefaultWithKey:@"cookies"];
for (NSHTTPCookie *cookie in setOfCookies) {
if (@available(iOS 11.0, *)) {
[webView.configuration.websiteDataStore.httpCookieStore setCookie:cookie completionHandler:^{}];
} else {
// Fallback on earlier versions
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
}
}
}
然后,加载请求。
现在,我们将使用 cookie 维护 webview 会话,因此在您的登录页面 webview 上,将 httpCookieStore 中的 cookie 保存到 viewDidDisappear 方法中的用户默认值中。
- (void)viewDidDisappear:(BOOL)animated {
if (isLoginPage) { //checking if it’s login page.
NSMutableSet *setOfCookies = [Helper getDataFromNSDefaultWithKey:@"cookies"]?[Helper getDataFromNSDefaultWithKey:@"cookies"]:[NSMutableArray array];
//Delete cookies if >50
if (setOfCookies.count>50) {
[setOfCookies removeAllObjects];
}
if (@available(iOS 11.0, *)) {
[webView.configuration.websiteDataStore.httpCookieStore getAllCookies:^(NSArray<NSHTTPCookie *> * _Nonnull arrCookies) {
for (NSHTTPCookie *cookie in arrCookies) {
NSLog(@"Cookie: \n%@ \n\n", cookie);
[setOfCookies addObject:cookie];
}
[Helper saveDataInNSDefault:setOfCookies key:@"cookies"];
}];
} else {
// Fallback on earlier versions
NSArray *cookieStore = NSHTTPCookieStorage.sharedHTTPCookieStorage.cookies;
for (NSHTTPCookie *cookie in cookieStore) {
NSLog(@"Cookie: \n%@ \n\n", cookie);
[setOfCookies addObject:cookie];
}
[Helper saveDataInNSDefault:setOfCookies key:@"cookies"];
}
}
[Helper saveDataInNSDefault:[self sharedWebViewPool] key:@"pool"];
}
注意:上述方法仅针对 iOS 11 进行了测试,虽然我已经写过
低版本的回退,但没有测试这些。
希望这能解决您的问题!!! :)