WKWebview
先來個最直觀的,為什么要用WKWebview
這里分別用WKWebview 和UIWebview加載了一個百度的網頁,內存的占用情況如下
- WKWebview
- UIWebview
相比之下,WKWebView占用20M,而UIWebView占用73M,這性能提升的不只一點點。
具體的要了解和使用 WKWebview 的,給個友情鏈接 劉彥瑋的技術博客
這里主要講下 WKWebViewJavascriptBridge ,一個優秀的第三方框架
WebViewJavascriptBridge
Github地址在這里
(https://github.com/marcuswestin/WebViewJavascriptBridge)
之前我也是自己封裝WK做的交互,后面偶然間看到的這個開源庫,8000+ star,果斷上手。 安卓那邊也有個類似這種的庫, 2000+ star,調用方法基本類似, 這樣 與前端的交互就可以只寫一套代碼了,輕松加愉快。
- 先做一個簡單Demo熟悉下
先導入
pod 'WebViewJavascriptBridge', '~> 5.0
看一下目錄
如果用UIwebview就導入WebViewJavascriptBridge。
WKWebViewJavascriptBridge 是后面加入的,用WKWebview要導入這個頭文件
這里用一個單例類用來管理交互 函數,像Cordova那種寫插件的形式,寫在一個類供JS調用,具體的可以看Demo。
- JS 調用 原生 方法
貼一下 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這個變量,看到報錯應該能發現在定義的時候有出錯
還有一個有意思的就是我設置了 _baseWebview.navigationDelegate=self;之后竟然也調用不了,JS端不走click()方法
貌似只能用 [_webViewBridge setWebViewDelegate:self];
這個方法,具體原因再看看。
