WKWebview

11 8月

Apple在ios2.0就提供了UIWebView用于加载网页,但它存在设计上的缺陷,导致内存泄漏问题,稳定性较差,而且随着前端的发展对HTML5,CSS3的支持开始变慢。所以Apple在ios8开始提供了全新的WKWebview用于取代之前的UIWebView,它们对外的功能是一样的,但底层实现几乎重写。

WKWebview的优势很明显,具有独立进程和内存,所以哪怕crash了也不影响主App,对前端的支持也更给力,执行JS的效率也更高。

和自定义组件一样,WKWebview提供了delegate,例如WKNavigationDelegate提供了页面加载跳转相关的方法:

decidePolicyForNavigationAction:是否加载请求(scheme拦截,特殊逻辑,JS与Native通信),例如点击页面电话弹出电话,就是通过这个方法执行的
didFinishNavigation:webView完成了加载,可以在这里处理业务逻辑
didFailNavigation:webView加载失败,例如显示错误信息,重试按钮等
webViewWebContentProcessDidTerminate:webView Crash回调,因为WKWebview有独立进程,所以万一代码中js执行导致crash,你也能在这个回调里重新创建WKWebview,重新加载页面

例如WKUIDelegate提供了页面常用的处理逻辑(但实际用的不多):

runJavaScriptAlertPanelWithMessage:处理alert()自定义样式
runJavaScriptConfirmPanelWithMessage:处理confirm()自定义样式
runJavaScriptTextInputPanelWithPrompt:处理prompt()自定义样式

使用WKWebview很简单:引入包,UIView里加载WKWebview,处理需要的delegate,发起网络请求:

#import <WebKit/WebKit.h>

@interface testViewController ()<WKNavigationDelegate>
@property(nonatomic, strong, readwrite) WKWebView *webView;
@end

[self.view addSubview:({
    self.webView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 88, self.view.frame.size.width, self.view.frame.size.height - 88)];
    self.webView.navigationDelegate = self;
    self.webView;
})];

[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://zxljack.com/"]]];

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    // 可以处理是否跳转 url
    decisionHandler(WKNavigationActionPolicyAllow);
}
- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation {
    // url 加载完后的处理
    NSLog(@"didFinishNavigation");
}

但webview并不能完全取代native,做不到和native一样的丝滑感受,尤其是在一些音视频方面,h5的video标签并不支持左滑右滑等手势。

可以在一个页面中webview和native并存,展示性的放在webview中,复杂交互性的放在native中。

但混用时,手势滚动是个问题,有一些常见的解决方案:

1.整个页面是UIScrollView,上半部分是webview,下半部分是UITableView。

2.整个页面是个UITableView,在header中展示webview。

可以使用开源项目,例如HybirdPagekit

发表评论

电子邮件地址不会被公开。 必填项已用*标注