UIWebView && MKWebView
- JS-Native interaction
# 从选择上看,使用依据如下:
- UIWebView 比 MKWebView 沉重一些, 从统一界面占用内存上看差不多是3 :1
- UIWebView 用于显示界面,实践证明,是没有MKWebView流畅的,但是后者只能支持(iOS 8)之后的系统,并且由于轻量级优势,功能上相对是有所限制的:
- UIWebView 对 JavaScriptCore 的支持,比较于 MKWebView ,能够实现功能更丰富,使用方式上有所区别,如果考虑到需要JS-Native 交互较多的情况下,UIWebView是更加强大的。
# 罗列部分参考文档:
- 《使用WKWebView替换UIWebView》
- 《How To Use iOS WKWebView with UIWebView Fallback》
- 《UIWebView和WKWebView的使用及js交互》
# 关于JS-Native交互,实现一个Demo,功能如下:
- UIWebView (JSContext 以及 JSExport 的使用)
- 通过 JSContext Block 调用 Native 实现A
- JS call Native 不传参数
- JS call Native 传参数
- JS call Native 传参数 并且给JS 返回值
- 通过 JSExport 调用 Native 实现B
- JS call Native 不传参数
- JS call Native 传参数
- JS call Native 传参数 并且给JS 返回值
- Native 通过 JSContext 调用 JS 代码C
- Native call JS 不传参数
- Native call JS 传参数
- JS call Native 传参数 并且给Native 返回值。
- 上面A和B两种调用效果是一样的, 但是注意 JSExport的使用方式,如果使用WebView所在的Controller直接去代理监听JS调用,那么 dealloc函数将会不会被触发,一次新建了一个WeakDelegate来作为JSExport协议的代理者,实现协议函数指针不与Controller存在直接引用关系,消除循环引用,dealloc函数得意正常释放。下面MKWebView的实现中,道理是一样的
- 从 ABC 三种形式看来,我们一般根据自己的需要,选择AC,或者BC的组合就可以实现绝大多数的JS—Native 之间的相互调用了。
2. MKWebView (WKScriptMessageHandler 以及 evaluateJavaScript: 的使用)
- Native 通过evaluateJavaScript:调用 JS 代码A
- Native call JS 不传参数
- Native call JS 传参数
- Native call JS 传参数 并且给Native 返回值
- 通过 WKScriptMessageHandler 调用 Native 实现B
- JS call Native 不传参数
- JS call Native 传参数
- 就目前寻找到调用处理而言,UIWebView可以实现传参以及带返回值的及时响应, 儿MKWebView中没有直接实现JS调用OC实现并且及时取得返回值得方法的,这是他作为轻量级的一个大弱点了吧?相当于是只实现了JS-Native的单项的消息流通 ~。
- 《查看demo 链接地址:XWJSC JS-Native》
界面效果:
- WebView load Source From Local
正常使用WebView(包括 UIWebView 和 MKWebView),那么直接加载URL:这里没什么好说的了,如果是需要加载本地资源,譬如本地Html模板,一般情况使用如下方法:
loadHTMLString:(NSString *)string baseURL:(nullable NSURL *)baseURL;
其中String 即是 .html 文件的字符串内容。
baseURL: 这个是个关键的东西,它所指向之外的目录,理论来说webview是不能加载资源的。
- case 模板搁置在工程目录即 [NSBundle mainBundle] 下面,那么baseURL 默认就是 [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];
- case 如果模板是下载过来的,那么是不能读入工程目录下的《you can see this》,这时候需要将baseURL使用为模板存储沙盒的所在目录中,for example,如果是在Cache目录,那么便是这个目录集合下的摸一个: NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
- 另外一个主意点,.html .css 还有 .js 这些所有的文件资源都需要搁置在同一个目录文件下,否则会出现webview 读取不出资源文件的情况的。
- 另外主意,资源文件命名方式也需要注意一下,不要使用含有%号,/ 这种存在文件夹歧义指示的特殊符号的文件名,否则读取不出,最好的方式就是纯字母数字以及下划线组成,.extension 等~ 。 对于Android 等处理 可以使用file:/// Directory ~.fileTpe 这样的路径结构来加载文件,当时在iOS中,这个在mainBundle中好使,跑到沙盒中去就不好使了,因此:所有资源文件可以放到沙盒的同一个目录中,在此前提下,加载直接使用文件名即可,不需要再添加文件引用路径。
NSString *setRecommendJS = [NSString stringWithFormat:@"setRecommend(%@)",jsonString];
[self.webView stringByEvaluatingJavaScriptFromString:setRecommendJS];
// ??? 调用下面的方法,导致界面卡顿的概率实在是太大了太大了 ,卡顿 ???
// dispatch_async(dispatch_get_main_queue(), ^{
// if (self.jsContext) {
// [self.jsContext evaluateScript:setRecommendJS];
// }
// });