介绍
UIWebView从 iOS2就已经有了,ios7时新加了框架JavaScriptCore.framework,用来做JS交互,当时主流的库WebViewJavascriptBridge,EasyJSWebView 原理是使用劫持页面加载的方法(js动作,js可以将要执行的操作封装到网络请求里面,然后oc拦截这个请求,获取url里面的字符串解析即可),iOS8 以后,苹果推出了新框架 WebKit,提供了替换 UIWebView 的组件 WKWebView。各种 UIWebView 的性能问题没有了,速度更快了,占用内存少了,体验更好了,下面列举一些其它的优势:
1、在性能、稳定性、功能方面有很大提升(加载速度,内存的提升谁用谁知道)
2、更多的支持 HTML5 的特性
3、官方宣称的高达60fps的滚动刷新率以及内置手势
4、Safari 相同的 JavaScript 引擎
5、将 UIWebViewDelegate 与 UIWebView 拆分成了14类与3个协议,包含该更细节功能的实现。
相比之下,WKWebView 复杂得多
代理
<WKScriptMessageHandler,WKNavigationDelegate,WKUIDelegate>
1.WKScriptMessageHandler 相应js调用代理 可以直接将接收到的JS脚本转为OC对象(当然,在UIWebView也可以通过“曲线救国”的方式与web进行交互,著名的Cordova框架就是这种
2.WKNavigationDelegate 导航代理 来追踪加载过程(页面开始加载、加载完成、加载失败)、决定是否执行跳转。
3.WKUIDelegate UI交互代理 创建新的WebView,界面弹出提示框相关的
初始化
//创建webView
-(void)creatWebView{
WKWebViewConfiguration *config = [WKWebViewConfiguration new];
//初始化偏好设置属性:preferences
config.preferences = [WKPreferences new];
//The minimum font size in points default is 0;
config.preferences.minimumFontSize = 10;
//是否支持JavaScript
config.preferences.javaScriptEnabled = YES;
//不通过用户交互,是否可以打开窗口
config.preferences.javaScriptCanOpenWindowsAutomatically = NO;
//通过JS与webView内容交互
config.userContentController = [WKUserContentController new];
// 注入JS对象名称senderModel,当JS通过senderModel来调用时,我们可以在WKScriptMessageHandler代理中接收到
[config.userContentController addScriptMessageHandler:self name:@"senderModel"];
self.webView = [[WKWebView alloc]initWithFrame:self.view.bounds configuration:config];
NSURL *path = [[NSBundle mainBundle] URLForResource:@"WKWebViewText" withExtension:@"html"];
[self.webView loadRequest:[NSURLRequest requestWithURL:path]];
[self.view addSubview:self.webView];
self.webView.navigationDelegate = self;
self.webView.UIDelegate = self;
}
流程
js调用WKWebview
初始化的时候WKUserContentController是用于给JS注入对象的,注入对象后,JS端就可以使用:window.webkit.messageHandlers.<对象名>.postMessage(<数据>)来发送数据
WKWebview调用js
[webView evaluateJavaScript:@"我是JS" completionHandler:^(id _Nullable response, NSError * _Nullable error) {
}];
问题
1.self没有释放
解决方法:
思路是另外创建一个代理对象,然后通过代理对象回调指定的self,
WKUserContentController *userContentController = [[WKUserContentController alloc] init];
[userContentController addScriptMessageHandler:[[WeakScriptMessageDelegate alloc] initWithDelegate:self] name:@"closeMe"];
运行代码,self释放了,WeakScriptMessageDelegate却没有释放啊啊啊!
还需在self的dealloc里面 添加这样一句代码:
[[_webView configuration].userContentController removeScriptMessageHandlerForName:@"closeMe"];
2.垮域名问题
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;
- 在里面进行域名的判断,
Cordova
CDVViewController有两个属性 wwwFolderName 和 startPage, wwwFolderName 的默认值为www,startPage 的默认值为 index.html
继承CDVPlugin 配置插件