WKWebView
一.WKWebViewConfiguration
1.WKPreferences
当前webview的相关设置
1 2 3 4 5 6 7 8
| WKPreferences *preferences = [[WKPreferences alloc] init]; // 最小字体 preferences.minimumFontSize = 100.0f; // 是否支持 web 调用 window.open() 打开新的空白窗口 (js自执行) preferences.javaScriptCanOpenWindowsAutomatically = YES; // 警告是否应该显示疑似欺诈内容,如网络钓鱼或恶意软件 preferences.fraudulentWebsiteWarningEnabled = NO;
|
2.WKUserContentController
用户脚本
1 2 3 4 5 6 7 8
| // 已经注入的用户脚本 @property (nonatomic, readonly, copy) NSArray<WKUserScript *> *userScripts;
// 利用 window.webkit.messageHandlers.<name>.postMessage(), 配合代理直接进行通信 - (void)addScriptMessageHandler:(id <WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name;
// 创建用户脚本,并选择注入时机和作用的Frame - (instancetype)initWithSource:(NSString *)source injectionTime:(WKUserScriptInjectionTime)injectionTime forMainFrameOnly:(BOOL)forMainFrameOnly;
|
二.WKNavigationDelegate
hook整个webview加载过程中的生命周期,通过decisionHandler让用户决定拦截自行处理或是继续进行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| /// ① 根据WebView对于即将跳转的HTTP请求头信息和相关信息来决定是否跳转 - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;
/// ② 页面开始加载 - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation;
/// ③ 根据客户端收到的服务器响应头以及response相关信息来决定是否可以跳转 - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler;
/// ④ 当内容开始返回时调用 - (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation;
/// ⑤ 页面加载完成之后调用 - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation;
/// 页面加载失败时调用 - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error;
/// Mainframe加载发生错误时调用 - (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error;
/// 服务重定向时之后调用 - (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation;
/// 身份验证时调用,同样在block中需要传入用户身份凭证, /// 1. 与使用自签名证书的服务器进行 HTTPS 连接。 /// 2. 进行更严格的服务器信任评估来加强安全性,如:通过使用 SSL Pinning 来防止中间人攻击。 - (void)webView:(WKWebView *)webView didReceiveAuthenticaqionChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler;
/// 进程被终止时调用,页面即将白屏 (iOS 9.0), eg:app内存耗尽~ - (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView;
|
三.WKUIDelegate
代表网页呈现本地UI。
1 2 3 4 5 6 7 8 9 10 11
| /// web 调用 alert() - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler;
/// web 调用 confirm() - (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler;
/// web 调用 prompt() - (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable))completionHandler;
/// 页面是弹出窗口处理 (subFrame) - (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures;
|
四.WKScriptMessageHandler
1 2 3 4
| /// 监听js中 window.webkit.messageHandlers.<name>.postMessage() 方式传递过来的数据 - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { }
|
五.缓存相关
1.NSURLRequest 缓存
NSURLRequestUseProtocolCachePolicy策略:

http和https缓存的详细文档:
https://imweb.io/topic/5795dcb6fb312541492eda8c
Cache In Http
总结:
请求头中的三个字段
Cache-Control : 控制缓存的行为 (no-cahce 确认返回的响应是否更改,若响应体Etag未变化, 请求还是会失败返回304)
If-Modified-Since: Last-Modified-value
If-Match (If-No-Match) : 上次请求成功的Etag
响应体:
Last-Modified:上一次修改时间
Etag: 一个可以与资源关联的唯一id
2.WKWebsiteDataStore
一个网站可能拥有的各种类型的数据缓存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| // 沙盒目录: Library/Caches/${BundleId}/WebKit/... NSString *targetHost = self.webView.URL.host; //allWebsiteDataTypes 所有类型的web缓存 NSSet *websiteDataTypes = [WKWebsiteDataStore allWebsiteDataTypes]; // 清除指定域名的缓存 [[WKWebsiteDataStore defaultDataStore] fetchDataRecordsOfTypes:websiteDataTypes completionHandler:^(NSArray<WKWebsiteDataRecord *> * _Nonnull dataRecords) { for (WKWebsiteDataRecord *dataRecord in dataRecords) { NSLog(@"缓存的域名:%@", dataRecord.displayName); if ([targetHost isEqualToString:dataRecord.displayName]) { [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:dataRecord.dataTypes forDataRecords:@[dataRecord] completionHandler:^{ }]; break; } } }]; NSDate *dateFrom = [NSDate dateWithTimeIntervalSince1970:0]; [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:websiteDataTypes modifiedSince:dateFrom completionHandler:^{
}];
|
</div>