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返回同步顯示。

實現

  1. 首先貼一下html和js代碼,這樣后面好敘述。
    test.html
  1.  
    <html>
  2.  
    <head>
  3.  
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  4.  
    <title>WebViewOCInvokeDemo</title>
  5.  
    <style>
  6.  
    *{
  7.  
    font-size: 50px;
  8.  
    }
  9.  
    .btn{height:80px; width:60%; padding: 0px 30px; background-color: #0071E7; border: solid 1px #0071E7; border-radius:5px; font-size: 1em; color: white}
  10.  
    </style>
  11.  
    <script src="test.js"></script>
  12.  
     
  13.  
    </head>
  14.  
     
  15.  
    <body>
  16.  
    <div>
  17.  
    <button class="btn" type="button" onclick="jsInvokeOC()">jsInvokeOC</button>
  18.  
    <br />
  19.  
    <button class="btn" type="button" onclick="getCookie()">invokeOCGetCookie</button>
  20.  
    </div>
  21.  
    <br/>
  22.  
    <div id="cookie">Cookie's value</div>
  23.  
    <br/>
  24.  
    <div id="response">response's value</div>
  25.  
    </body>
  26.  
    </html>

test.js

  1.  
    function jsInvokeOC() {
  2.  
    window.webkit.messageHandlers.jsInvokeOCMethod.postMessage('Javascript invoke OC');
  3.  
    }
  4.  
     
  5.  
    function getCookie() {
  6.  
    var cookie = window.prompt("getCookie");
  7.  
     
  8.  
    document.getElementById('cookie').innerText = "cookie: " + cookie;
  9.  
    }
  10.  
     
  11.  
    function response2JS(response) {
  12.  
    document.getElementById('response').innerText = "resp: " + response;
  13.  
    }
  1. 對於第一個按鈕觸發的方法是由下面這行代碼調用的。
window.webkit.messageHandlers.jsInvokeOCMethod.postMessage('Javascript invoke OC'); 

該方法的的原型是:
window.webkit.messageHandlers.<方法名>.postMessage(<消息內容>);
<方法名>是和oc之間商量好的方法名,用於oc判斷;
<消息內容>用於發給oc的消息內容字符串。

這種方法的實現需要WKWebViewConfiguration的WKUserContentController添加對<方法名>的消息監聽,觸發后在代理方法:

  1.  
    - ( void)userContentController:(WKUserContentController *)userContentController
  2.  
    didReceiveScriptMessage:( WKScriptMessage *)message;

中通過判斷message.name獲取<方法名>,通過message.body獲取<消息內容>。
實現代碼如下:
(1)配置WKUserContentController。

  1.  
    - ( WKWebView*)webView {
  2.  
    if (!_webView) {
  3.  
    WKWebViewConfiguration* configuration = [[WKWebViewConfiguration alloc]
  4.  
    init];
  5.  
     
  6.  
    _webView = [[ WKWebView alloc] initWithFrame: CGRectZero
  7.  
    configuration: configuration];
  8.  
     
  9.  
    WKUserContentController* userCC = _webView.configuration.userContentController;
  10.  
     
  11.  
    [userCC addScriptMessageHandler: self
  12.  
    name: @"jsInvokeOCMethod"];
  13.  
     
  14.  
    _webView.UIDelegate = self;
  15.  
    _webView.navigationDelegate = self;
  16.  
    }
  17.  
     
  18.  
    return _webView;
  19.  
    }

(2)實現回調方法。

  1.  
    #pragma mark - WKScriptMessageHandler
  2.  
    - ( void)userContentController:(WKUserContentController *)userContentController
  3.  
    didReceiveScriptMessage:( WKScriptMessage *)message {
  4.  
    if ([message.name isEqualToString: @"jsInvokeOCMethod"]) {
  5.  
    NSLog(@"MessageBody: %@", message.body);
  6.  
     
  7.  
    // async return value
  8.  
    [ self.webView evaluateJavaScript: @"response2JS('Hello return')"
  9.  
    completionHandler:^( id response, NSError * error) {
  10.  
    NSLog(@"response: %@, \nerror: %@", response, error);
  11.  
    }];
  12.  
    }
  13.  
    }

實現回調方法中調用了evaluateJavaScript是為了異步調用js方法來返回值,其中response2JS('Hello return')是js方法,在文件test.js中。
當然此處可以不用異步返回,直接進行某種操作,比如oc中的彈框,popViewController或者是pushViewController操作。

  1. 第二個按鈕的觸發實現操作如下。
    第二個按鈕直接觸發的語句為:
var cookie = window.prompt("getCookie"); 

直接獲取cookie,prompt方法會直接被oc的WKUIDelegate代理中的runJavaScriptTextInputPanelWithPrompt代理方法所捕獲到。
prompt有兩個參數,第一個是prompt,第二個defaulttext,分別和代理方法中相對應。
代理方法實現如下:

  1.  
    #pragma mark - WKUIDelegate delegate method
  2.  
    - (void)webView:(WKWebView *)webView
  3.  
    runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt
  4.  
    defaultText:(NSString *)defaultText
  5.  
    initiatedByFrame:(WKFrameInfo *)frame
  6.  
    completionHandler:(void (^)(NSString * _Nullable))completionHandler {
  7.  
    if (prompt) {
  8.  
    if ([prompt isEqualToString: @"getCookie"]) {
  9.  
    completionHandler(@"eba7392f-f754-4a56-9c22-aedf3ffb79d8");
  10.  
    }
  11.  
    }
  12.  
    }

這樣由js調用oc便實現了。

結束語

本文沒有使用第三方庫的實現,只是調研了原生的類庫的使用方式。其實可以研究一下第三方類庫wkwebviewjavascriptbridge,這樣可以保證前端只寫一份代碼,可以在iOS和Android上共同使用。

 

微信公號搜索:李大頭頭。(或掃描二維碼)找我來玩。

更多【前端技術群】和【內推職位】 資源等着你。

還不定期在公眾號請大家喝奶茶!

想與我聊聊或者有什么問題都可以在公眾號找到我。

等你喲~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM