WKWebview 和 WebViewJavascriptBri
有个要提前说一下,WKWebview cookie 与Native 的 cookie 是分开的,在接入WKWebview 的时候发现无法同步cookie,试过很多方法,还是不行。
最后还是不甘心的换回了webView, 如果有解决这个问题的麻烦指教一下,给你红包,哈哈。
不管怎么样,多知道些东西总是好的。
WKWebview
先来个最直观的,为什么要用WKWebview
这里分别用WKWebview 和UIWebview加载了一个百度的网页,内存的占用情况如下
- WKWebview
- UIWebview
相比之下,WKWebView占用20M,而UIWebView占用73M,这性能提升的不只一点点。具体的要了解和使用 WKWebview 的,给个友情链接 刘彦玮的技术博客
这里主要讲下 WKWebViewJavascriptBridge ,一个优秀的第三方框架
之前我也是自己封装WK做的交互,后面偶然间看到的这个开源库,8000+ star,果断上手。 安卓那边也有个类似这种的库, 2000+ star,调用方法基本类似, 这样 与前端的交互就可以只写一套代码了,轻松加愉快。
先做一个简单Demo熟悉下
先导入
pod 'WebViewJavascriptBridge', '~> 5.0
如果用UIwebview就导入WebViewJavascriptBridge。
WKWebViewJavascriptBridge 是后面加入的,用WKWebview要导入这个头文件
这里用一个单例类用来管理交互 函数,像Cordova那种写插件的形式,写在一个类供JS调用,具体的可以看Demo。
html 的代码段落
贴一下 demo.html 的 JS 段落 ,看注释,主要知道JS 怎么调用 原生方法 和 注册JS方法 供JS调用
<script type="text/javascript">
//这是必须要写的,用来初始化一些设置
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)
}
//这也是固定的, OC 调JS , 需要给OC调用的函数必须写在这个函数里面
setupWebViewJavascriptBridge(function(bridge) {
bridge.registerHandler('testJSFunction', function(data, responseCallback) {
alert('JS方法被调用:'+data);
responseCallback('js执行过了');
})
})
//这个 shareClick 就是 原生那边 注入的函数 , 通过这个方法来调用原生 和传值
//parmas 是JS 给OC的数据 , response 是 OC函数被调用之后 再 告诉JS 我被调用了
//比如微信分享,给Dic给原生 , 原生分享成功后再把结果回调给JS 进行处理
function shareClick() {
var params = {'title':'测试分享的标题','content':'测试分享的内容','url':'http://www.baidu.com'};
WebViewJavascriptBridge.callHandler('shareClick',params,function(response) {
console.log(response);
});
}
</script>
原生代码
//初始化
#import "WKWebViewJavascriptBridge.h" //注意是 WK 开头的 , 如果不需要适配8.0以下的可以直接就用WKWebview
@property WebViewJavascriptBridge* bridge;
self.bridge = [WebViewJavascriptBridge bridgeForWebView:webView];
//注册原生方法给JS调用
- (void)registShareFunction
{
[_webViewBridge registerHandler:@"shareClick" handler:^(id data, WVJBResponseCallback responseCallback) {
// data 的类型与 JS中传的参数有关
NSDictionary *tempDic = data;
// 在这里执行分享的操作
NSString *title = [tempDic objectForKey:@"title"];
NSString *content = [tempDic objectForKey:@"content"];
NSString *url = [tempDic objectForKey:@"url"];
// 将分享的结果返回到JS中
NSString *result = [NSString stringWithFormat:@"分享成功:%@,%@,%@",title,content,url];
responseCallback(result); //回调给JS
}];
}
//原生调用JS , JS 中先声明testJSFunction 函数
-(void)pp_hander
{
//testJSFunction 是JS的方法
[_webViewBridge callHandler:@"testJSFunction" data:@"一个字符串" responseCallback:^(id responseData) {
NSLog(@"调用完JS后的回调:%@",responseData);
}];
}
基本用法差不多就这些,很简洁,用起来也挺简单,准备接入目前的项目使用。
如果不知道在模拟器怎么看调试网页,可以看看淘宝前端团队的这篇 在 iOS 模拟器中调试 Web 页面
Safari的开发者选项,如果没有,去偏好设置->高级->显示开发者选项就有了
如果调用不成功,可能是这些原因
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)
}
写在JS里的代码这里是不能动的,原样贴上去就行。 之前有一次莫名其妙老是调用不了OC的方法, 后来发现是
window.WebViewJavascriptBridg 写成了 window.WebView JavascriptBridg, 一直没看到,在网页端一直报找不到 WebViewJavascriptBridg这个变量,看到报错应该能发现在定义的时候有出错