javascript
iOS下JS与OC互相调用(六)--WKWebView + WebViewJavascriptBridge
2019獨角獸企業重金招聘Python工程師標準>>>
iOS下JS與OC互相調用(六)--WKWebView + WebViewJavascriptBridge
轉載:原地址?https://www.jianshu.com/p/e951af9e5e74
上一篇文章介紹了UIWebView 如何通過WebViewJavascriptBridge 來實現JS 與OC 的互相調用,這一篇來介紹一下WKWebView 又是如何通過WebViewJavascriptBridge 來實現JS 與OC 的互相調用的。WKWebView 下使用WebViewJavascriptBridge與UIWebView 大同小異。主要是示例化的類不一樣,一些與webView 相關的API調用不一樣罷了。
?
WKWebView 下使用WebViewJavascriptBridge來實現JS 與OC 的互相調用,也是通過攔截URL來實現的。
下面開始介紹WKWebView 如何通過WebViewJavascriptBridge 來實現JS 與OC 的互相調用。
關于下載WebViewJavascriptBridge,然后導入工程的部分就不再贅述了。
第一步,創建WKWebView。
這一步,唯一需要注意的地方,就是不用再設置WKWebView?的navigationDelegate,下一步你就知道為什么了。
- (void)initWKWebView {WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];configuration.userContentController = [WKUserContentController new];WKPreferences *preferences = [WKPreferences new];preferences.javaScriptCanOpenWindowsAutomatically = YES;preferences.minimumFontSize = 30.0;configuration.preferences = preferences;self.webView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:configuration];NSString *urlStr = [[NSBundle mainBundle] pathForResource:@"index.html" ofType:nil];NSString *localHtml = [NSString stringWithContentsOfFile:urlStr encoding:NSUTF8StringEncoding error:nil];NSURL *fileURL = [NSURL fileURLWithPath:urlStr];[self.webView loadHTMLString:localHtml baseURL:fileURL];self.webView.UIDelegate = self;[self.view addSubview:self.webView]; }第二步,創建WebViewJavascriptBridge實例。
這里與上一篇文章有一些不同,WKWebView 使用的是WKWebViewJavascriptBridge,而UIWebView 使用的是WebViewJavascriptBridge。
? _webViewBridge = [WKWebViewJavascriptBridge bridgeForWebView:self.webView]; // 如果控制器里需要監聽WKWebView 的`navigationDelegate`方法,就需要添加下面這行。 [_webViewBridge setWebViewDelegate:self];上一步說了不用再設置WKWebView?的navigationDelegate,那是因為在{-bridgeForWebView:}內已經將WKWebView?的navigationDelegate設置為WKWebViewJavascriptBridge的實例了。
? + (instancetype)bridgeForWebView:(WKWebView*)webView {WKWebViewJavascriptBridge* bridge = [[self alloc] init];[bridge _setupInstance:webView];[bridge reset];return bridge; }- (void) _setupInstance:(WKWebView*)webView {_webView = webView;_webView.navigationDelegate = self;_base = [[WebViewJavascriptBridgeBase alloc] init];_base.delegate = self; }第三步,注冊 js 要調用的Native 功能
為了便于維護,我將所有js 要調用Native 功能放在了一個方法里添加,然后每個功能再單獨處理。
示例代碼如下:
關于- (void)registerHandler:(NSString *)handlerName handler:(WVJBHandler)handler,我們可以這樣理解,后面的block 參數是js 要調用的Native 實現,前面的handlerName 是這個Native 實現的別名。然后js 里調用handlerName 這個別名,WebViewJavascriptBridge最終會執行block 里的Native 實現。
第四步,在HTML添加關鍵的js
HMTL 里在調用Native 功能之前,要先添加一個js 方法,然后主動調用一次該方法。
要添加的方法是:
如果你看過iOS下JS與OC互相調用(一)--UIWebView 攔截URL,你就會發現這個方法與loadURL很像。
然后在js 中要主動調用一次上述的setupWebViewJavascriptBridge。
主動調用setupWebViewJavascriptBridge有兩個目的:
1、執行一次wvjbscheme://__BRIDGE_LOADED__請求。
2、注冊Native 要調用的js 功能。
執行wvjbscheme://__BRIDGE_LOADED__,然后在WKWebView 的navigationDelegate方法中攔截該URL ,然后往HMTL中注入js。以下源碼都摘自WebViewJavascriptBridge:
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {if (webView != _webView) { return; }NSURL *url = navigationAction.request.URL;__strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate;if ([_base isCorrectProcotocolScheme:url]) {// 在這里攔截wvjbscheme://__BRIDGE_LOADED__if ([_base isBridgeLoadedURL:url]) {// 這里會注入js [_base injectJavascriptFile];} else if ([_base isQueueMessageURL:url]) {[self WKFlushMessageQueue];} else {[_base logUnkownMessage:url];}decisionHandler(WKNavigationActionPolicyCancel);}if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:decidePolicyForNavigationAction:decisionHandler:)]) {[_webViewDelegate webView:webView decidePolicyForNavigationAction:navigationAction decisionHandler:decisionHandler];} else {decisionHandler(WKNavigationActionPolicyAllow);} }- (void)injectJavascriptFile {//讀取js 內容NSString *js = WebViewJavascriptBridge_js();// 執行Native 的API,實現將js 注入 到HMTL中。[self _evaluateJavascript:js];if (self.startupMessageQueue) {NSArray* queue = self.startupMessageQueue;self.startupMessageQueue = nil;for (id queuedMessage in queue) {[self _dispatchMessage:queuedMessage];}} }WKWebView 執行js 的API 與 UIWebView 有些不同,WKWebView 用的是{-evaluateJavaScript: completionHandler:},這個API 不會立刻返回執行結果,js 的執行結果會在block 中返回。
第五步,在js 中調用 Native 功能。
講完過程,終于到了 js 調用Native 的用法了。其實非常的簡單,例如我想要利用Native 獲取定位信息,那么在HTML中添加一個按鈕,onclick事件是locationClick(),按照如下實現即可。
function locationClick() {WebViewJavascriptBridge.callHandler('locationClick',null,function(response) {alert(response);document.getElementById("returnValue").value = response;}); }Native 執行完代碼,將獲取到的定位信息,通過callHandler 的第三方參數,回調返回到js 中。
response 可以是單個值,也可以是數組、鍵值對等。
當然如果我們調用Native 的時候,沒有參數或者不需要Native 返回信息到js 中。我們還可以這樣寫:
至此,JS 通過WebViewJavascriptBridge調用Native 的功能就完成了。
第六步,Native 調用 JS 功能。
Native 調用js 功能與 js 調用Native 的原理和流程一樣。
1、現在js 中注冊,Native 要調用的功能。
2、Native 調用注冊時,該功能的別名,就可以完成調用。
在js 中注冊 Native 要調用的功能,同樣需要為該功能設置一個別名HandlerName。
其實這個步驟在前面介紹過,代碼如下:
上述代碼,是在JS 中注冊了一個別名叫testJSFunction的js功能,第二個參數是一個function。function里的data ,就是Native 調用該功能時傳過來的參數,responseCallback是執行完js 代碼后,通過responseCallback將必要的信息返回到Native中。
Native 調用js 里注冊的功能,示例代碼:
- (void)rightClick {// // 如果不需要參數,不需要回調,使用這個// [_webViewBridge callHandler:@"testJSFunction"];// // 如果需要參數,不需要回調,使用這個// [_webViewBridge callHandler:@"testJSFunction" data:@"一個字符串"];// 如果既需要參數,又需要回調,使用這個[_webViewBridge callHandler:@"testJSFunction" data:@"一個字符串" responseCallback:^(id responseData) {NSLog(@"調用完JS后的回調:%@",responseData);}]; }WKWebView 通過WebViewJavascriptBridge實現js 與Native 的交互,到這里就已經完成了。
這是工程示例中的效果圖:
示例工程地址:JS_OC_WebViewJavascriptBridge
Have Fun!
轉載于:https://my.oschina.net/fadoudou/blog/1810887
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的iOS下JS与OC互相调用(六)--WKWebView + WebViewJavascriptBridge的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: API设计中防重放攻击
- 下一篇: 在EF中使用SQL执行简单高效的增删查操