iOS中js呼叫oc獲取返回值(WKWebView)
https://blog.csdn.net/ljy_1024/article/details/92633698
前言
最近公司的APP需要進行hybrid模式的開發,即native和h5聯合開發。此時前端工程師提到了一個需求,由前端呼叫native進行操作以及獲取返回值。這樣可以保證native只有一份程式碼,h5不用指定方法和native進行確認。為了實現這個需求,從網上的給出的解決辦法來看,一種是使用原生的類和庫方法,另外一種是使用第三方庫。本文主要介紹使用原生類庫進行操作。
實現效果(demo)
demo實現效果
在實現效果圖中,當前view是載入了wkwebview的例項,並且wkwebview載入了本地的html,介面上jsInvokeOC和invokeOCGetCookie是兩個button。jsInvokeOC點選之後會呼叫native方法,而native方法又呼叫了js方法將結果非同步傳給html用於顯示,也可以不進行顯示直接在native中做相當的動作,比如返回上一級。下面的invokeOCGetCookie是直接呼叫的native,由native返回同步顯示。
實現
- 首先貼一下html和js程式碼,這樣後面好敘述。
test.html
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>WebViewOCInvokeDemo</title>
- <style>
- *{
-
font-size: 50px;
- }
- .btn{height:80px; width:60%; padding: 0px 30px; background-color: #0071E7; border: solid 1px #0071E7; border-radius:5px; font-size: 1em; color: white}
- </style>
- <script src="test.js"></script>
- </head>
- <body>
- <div>
- <button class="btn" type="button" onclick="jsInvokeOC()">jsInvokeOC</button>
- <br />
- <button class="btn" type="button" onclick="getCookie()">invokeOCGetCookie</button>
- </div>
- <br/>
- <div id="cookie">Cookie's value</div>
- <br/>
- <div id="response">response's value</div>
- </body>
- </html>
test.js
- function jsInvokeOC() {
- window.webkit.messageHandlers.jsInvokeOCMethod.postMessage('Javascript invoke OC');
- }
- function getCookie() {
- var cookie = window.prompt("getCookie");
- document.getElementById('cookie').innerText = "cookie: " + cookie;
- }
- function response2JS(response) {
- document.getElementById('response').innerText = "resp: " + response;
- }
- 對於第一個按鈕觸發的方法是由下面這行程式碼呼叫的。
window.webkit.messageHandlers.jsInvokeOCMethod.postMessage('Javascript invoke OC');
該方法的的原型是:
window.webkit.messageHandlers.<方法名>.postMessage(<訊息內容>);
<方法名>是和oc之間商量好的方法名,用於oc判斷;
<訊息內容>用於發給oc的訊息內容字串。
這種方法的實現需要WKWebViewConfiguration的WKUserContentController新增對<方法名>的訊息監聽,觸發後在代理方法:
- - (void)userContentController:(WKUserContentController *)userContentController
- didReceiveScriptMessage:(WKScriptMessage *)message;
中通過判斷message.name獲取<方法名>,通過message.body獲取<訊息內容>。
實現程式碼如下:
(1)配置WKUserContentController。
- - (WKWebView*)webView {
- if (!_webView) {
- WKWebViewConfiguration* configuration = [[WKWebViewConfiguration alloc]
- init];
- _webView = [[WKWebView alloc] initWithFrame: CGRectZero
- configuration: configuration];
- WKUserContentController* userCC = _webView.configuration.userContentController;
- [userCC addScriptMessageHandler: self
- name: @"jsInvokeOCMethod"];
- _webView.UIDelegate = self;
- _webView.navigationDelegate = self;
- }
- return _webView;
- }
(2)實現回撥方法。
- - (void)userContentController:(WKUserContentController *)userContentController
- didReceiveScriptMessage:(WKScriptMessage *)message {
- if ([message.name isEqualToString: @"jsInvokeOCMethod"]) {
- NSLog(@"MessageBody: %@", message.body);
- // async return value
- [self.webView evaluateJavaScript: @"response2JS('Hello return')"
- completionHandler:^(id response, NSError * error) {
- NSLog(@"response: %@, \nerror: %@", response, error);
- }];
- }
- }
實現回撥方法中呼叫了evaluateJavaScript是為了非同步呼叫js方法來返回值,其中response2JS('Hello return')是js方法,在檔案test.js中。
當然此處可以不用非同步返回,直接進行某種操作,比如oc中的彈框,popViewController或者是pushViewController操作。
- 第二個按鈕的觸發實現操作如下。
第二個按鈕直接觸發的語句為:
var cookie = window.prompt("getCookie");
直接獲取cookie,prompt方法會直接被oc的WKUIDelegate代理中的runJavaScriptTextInputPanelWithPrompt代理方法所捕獲到。
prompt有兩個引數,第一個是prompt,第二個defaulttext,分別和代理方法中相對應。
代理方法實現如下:
- #pragma mark - WKUIDelegate delegate method
- - (void)webView:(WKWebView *)webView
- runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt
- defaultText:(NSString *)defaultText
- initiatedByFrame:(WKFrameInfo *)frame
- completionHandler:(void (^)(NSString * _Nullable))completionHandler {
- if (prompt) {
- if ([prompt isEqualToString: @"getCookie"]) {
- completionHandler(@"eba7392f-f754-4a56-9c22-aedf3ffb79d8");
- }
- }
- }
這樣由js呼叫oc便實現了。
結束語
本文沒有使用第三方庫的實現,只是調研了原生的類庫的使用方式。其實可以研究一下第三方類庫wkwebviewjavascriptbridge,這樣可以保證前端只寫一份程式碼,可以在iOS和Android上共同使用。
微信公號搜尋:李大頭頭。(或掃描二維碼)找我來玩。
更多【前端技術群】和【內推職位】 資源等著你。
還不定期在公眾號請大家喝奶茶!
想與我聊聊或者有什麼問題都可以在公眾號找到我。
等你喲~