WebKit的加载本文从WKWebView网页加载流程、代理方法、代理方法初步了解WKWebView
第三方源码:
WebViewJavascri源码
网页加载流程
- DNS解析【域名-ip】
- 请求握手
- 获取html文件
- 解析html文件,异步加载css或资源。碰到js会挂起html解析,进行js请求。
- 解析完毕html,执行js代码,成型dom树,配合css,展示样式
- 结束链接
WKNavigationDelegate代理方法
@protocol WKNavigationDelegate <NSObject>
@optional
// 请求之前,决定是否要跳转:用户点击网页上的链接,需要打开新页面时,将先调用这个方法。
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;
// 页面开始加载时调用
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation;
// 接收到响应数据后,决定是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler;
// 主机地址被重定向时调用
- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(null_unspecified WKNavigation *)navigation;
// 当开始加载主文档数据失败时调用
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error;
// 当内容开始返回时调用
- (void)webView:(WKWebView *)webView didCommitNavigation:(null_unspecified WKNavigation *)navigation;
// 页面加载完毕时调用
- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation;
// 当主文档已committed时,如果发生错误将进行调用
- (void)webView:(WKWebView *)webView didFailNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error;
// 如果需要证书验证,进行验证,一般使用默认证书策略即可
- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *__nullable credential))completionHandler;
// 9.0才能使用,web内容处理中断时会触发,可针对该情况进行reload操作,可解决部分白屏问题
- (void)webVididStartProvisionalNavigationewWebContentProcessDidTerminate:(WKWebView *)webView NS_AVAILABLE(10_11, 9_0);
@end
decidePolicyForNavigationAction
请求之前,决定是否要跳转:用户点击网页上的链接,需要打开新页面时,将先调用这个方法。业务(拨打电话)
当WebContent即将创建DocumentLoader加载器时,会触发此方法。
cancel
:那么浏览器内核会完全忽略这已操作,后续不再执行其他操作。
allow
:内核代码会判断该链接是否universalLink
,为此链接会尝试调起三方app,能调起取消当前请求。否则会走正常的网络请求
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
// NSURL *URL = navigationAction.request.URL;
NSString *urlString = navigationAction.request.URL.absoluteString;
if ([urlString hasPrefix:@"tel:"] || [urlString hasPrefix:@"weixin:"]) {
[[UIApplication sharedApplication] openURL:navigationAction.request.URL];
decisionHandler(WKNavigationActionPolicyCancel);
}else {
if (navigationAction.targetFrame == nil) {
[webView loadRequest:navigationAction.request];
}
decisionHandler(WKNavigationActionPolicyAllow);
}
}
didStartProvisionalNavigation
decidePolicyForNavigationAction
选择allow
,并且非universalLink
会触发didStartProvisionalNavigation
,表示开始加载主文档,
// 页面开始加载时调用
-(void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation{
if (![webView.URL.absoluteString containsString:@"about:blank"]) {
[SVProgressHUD show];
}
if ([webView.URL.absoluteString containsString:@"voteindex"])
{
self.webView.scrollView.bounces = YES;
}else
{
self.webView.scrollView.bounces = NO;
}
self.shareUrl = webView.URL.absoluteString;
}
decidePolicyForNavigationResponse
页面加载后为了更好区分各个阶段,会将网络加载的初始阶段命名为临时状态,此时页面不会计入历史,decidePolicyForNavigationResponse
为收到响应的之后处理,是否允许跳转
// 在收到响应后,决定是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{
NSLog(@"decidePolicyForNavigationResponse:%@",navigationResponse.response.URL.absoluteString);
//允许跳转
decisionHandler(WKNavigationResponsePolicyAllow);
//不允许跳转
//decisionHandler(WKNavigationResponsePolicyCancel);
}
didCommitNavigation
直到收到首个数据包,才会进行commit提交,执行。通知进程UIProcess
,将网络数据交给WebContent
进行渲染。此时网络临时状态处理处理果和提交处理结果如果失败,执行下面两种方法
// 当内容开始返回时调用
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation{
NSLog(@"didCommitNavigation");
}
didFailProvisionalNavigation/didFailNavigation
当NetProcess进程发生网络错误时,错误首先由NSURLSession
回调给WebContent
层
WebContent判断主文档的加载状态,如果处于临时Provisional
状态,则错误回调给didFailProvisionalNavigation
,如果是提交commit
状态,则错误回调给didFailNavigation
// 页面加载失败时调用
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error {
NSLog(@"didFailProvisionalNavigation:%@",error);
}
- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error {
NSLog(@"didFailNavigation:%@",error);
}
didFinishNavigation
NetworkProcess
层也是使用NSURLSession
加载主文档,当NSURLSession
接收到finish
事件,会将该消息通过进程通信传递给WebContent
进程,然后传递给UIProcess
进程,直到被代理方法响应
因此didFinishNavigation
的加载与子界面上屏没有关系,在网络加载结束触发
// 页面加载完成之后调用
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{
NSLog(@"加载完毕");
}
网友评论