【进阶篇】iOS使用WKWebView混编开发
使用WKWebView配合JS混编开发一个复杂布局,高度可定制的新闻详情页。
新闻详情页面,算是UI中较为复杂一种,因为其中不乏会包括以下的功能:
1、HTML的内容展示
2、夜间模式切换
3、字体大小变更
4、评论回复功能
5、评论列表的更新
在iOS中关于新闻详情这类需求的解决方案有很多:
1、native
开发上难度比较大,而且也需要后台来配合样式协议的制定,优点是原生的东西,在体验以及各个方面都会很好,缺点也同样的,原生的这种做法开发成本很大。
2、Hybrid
使用webView先显示HTML页面内容,通过与JS的通信来控制HTML页面中的DOM,优点:几乎不用太多去考虑布局的问题,使用模板的形式将要显示的数据塞进HTML模板中即可,通过OC和JS中通信来达到JS调用OC,或者OC调用JS;缺点:在H5出来这么久的今天,用户体验上依然不及原生,并且一些系统级的功能组件调用比较麻烦。
今天主要说的是Hybrid
这种解决方案,在iOS8以前,iOSApp中使用的是UIWebView来加载web页面,iOS8以后,Apple推出了新的框架WebKit
,其中将 UIWebViewDelegate 与 UIWebView 重构成了 14 个类和 3 个协议,引入了不少新的功能和接口。
WKWebView 有以下几大主要进步:
1、将浏览器内核渲染进程提取出 App,由系统进行统一管理,这减少了相当一部分的性能损失。
2、js 可以直接使用已经事先注入 js runtime 的 js 接口给 Native 层传值,不必再通过苦逼的 iframe 制造页面刷新再解析自定义协议的奇怪方式。
3、支持高达 60 fps 的滚动刷新率,内置了手势探测。
以上特性摘自别人的话,说白了就是使用WKWebView比UIWebView性能和内存占用上都会好很多,如果要进行Hybrid开发,在iOS8之后,强烈推荐使用
WKWebView,因为同样的内容,在使用UIWebView时比WKWebView要慢很多,这在体验上是很致命的。
使用
WKWebViewJavascriptBridge GitHub地址
Objective-C
引用库
#import <WebKit/WebKit.h>
#import "WKWebViewJavascriptBridge.h"
初始化
WKWebView* webView = [[WKWebView alloc] init];
webView.navigationDelegate = self;
webView.UIDelegate = self;
[self.view addSubview:webView];
self.webView = webView;
//打开WKWebViewJavascriptBridge 的log
[WKWebViewJavascriptBridge enableLogging];
self.bridge = [WKWebViewJavascriptBridge bridgeForWebView:webView];
//设置代理
[self.bridge setWebViewDelegate:self];
加载本地的HTML文件
NSString* htmlPath = [[NSBundle mainBundle] pathForResource:@"Test" ofType:@"html"];
NSString* appHtml = [NSString stringWithContentsOfFile:htmlPath encoding:NSUTF8StringEncoding error:nil];
NSURL *baseURL = [NSURL fileURLWithPath:htmlPath];
[webView loadHTMLString:[self replaceWithModelAppHemlString:appHtml] baseURL:baseURL];
绑定Handler
//registerHandler 【OC接收JS的消息】
[self.bridge registerHandler:@"ClickTest" handler:^(id data, WVJBResponseCallback responseCallback) {
NSLog(@"%@",data);
}];
//callHandler【OC向JS发生消息】
id data = @{ @"test": @"news" };
[self.bridge callHandler:@"ClickTest" data:data responseCallback:^(id response) {
}];
JavaScirpt
初始化
// WebViewJavascriptBridge 初始化
function setupWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) {
return callback(WebViewJavascriptBridge);
}
if (window.WVJBCallbacks) {
return window.WVJBCallbacks.push(callback);
}
window.WVJBCallbacks = [callback];
var WVJBIframe = document.createElement('iframe');
WVJBIframe.style.display = 'none';
WVJBIframe.src = 'wvjbscheme://__BRIDGE_LOADED__';
document.documentElement.appendChild(WVJBIframe);
setTimeout(function() {
document.documentElement.removeChild(WVJBIframe)
}, 0)
}
//WebViewJavascriptBridge 绑定事件
setupWebViewJavascriptBridge(function(bridge) {
//registerHandler【JS接收OC的消息】
bridge.registerHandler('ClickTest', function(data, responseCallback) {
//改变背景颜色为黑色【Jquery操作DOM】
$("body").css("backgroundColor","#000000");
})
//callHandler【JS向OC发送消息】
bridge.callHandler('ClickTest', {'test': 'value'}, function responseCallback(responseData) {
})
}
注意事项
1、使用WKWebView加载本地的HTML,在iOS8不能在HTML文件中引用本地的css或者js或者图片文件,只能在iOS9中这么做,iOS8需要将文件copy到temp文件夹中才行,所有不建议使用外部的css和js,可以引用远程的。
2、在iOS8中,使用一些远程的cdn的css或者js文件,必须注意在引用标签上加上charset属性,不然css和js库将会乱码
3、WKWebView性能比UIViewView性能好很多,谁用谁知道。
演示和demo查看
换个心情去思考问题,也许很多难题就会迎刃而解。