OC與JS交互之UIWebView


 

 

隨着H5的強大,hybrid app已經成為當前互聯網的大方向,單純的native app和web app在某些方面顯得就很劣勢。關於H5的發展史,這里有一篇文章推薦給大家,今天我們來學習最基礎的基於iOS系統的OC與JS之間是如何進行交互的,本文介紹的是基於UIWebView"協議攔截"實現的交互方式,當然后面還會循序漸進的介紹其他的交互方式。這里的說到的JS指的是廣義上JS,並不是單純的javascript,你可以理解為web前端的三件套(html+css+javascript);這里說的OC指的是iOS的系統語言Objective-C,為什么叫做OC與JS交互而不是iOS與JS交互或者其他名字,這個不是重點,也有叫web交互,H5交互的。本着盡可能清楚解釋原理的目標,文章的組織形式采用圖文並茂加示例代碼

 

先來一張圖,如下。簡要說明下:界面分為兩部分,上半部分是UIWebView加載的本地html頁面,下半部分是原生UI繪制的界面。我們這里需要實現的功能是,分別點擊上面的(小黃)三個按鈕,會執行OC里面對應的無參,1個參數,2個參數的方法;點擊下面的(小紅)三個按鈕,會執行HTML里面對應的無參,1個參數,2個參數的JS方法。下面的介紹會結合這張圖,及相關代碼來詮釋如何用原生UIWebView攔截協議的方式實現JS交互的。本文的示例代碼會放在文章的后面,需要的同學拿去不謝,可以先下載示例DEMO查看效果

 

OC與JS交互是雙向的,一方面是OC向JS發送消息,另一方面是JS向OC發送消息。代碼上的表現形式就是方法的相互調用,分為兩種:

 

一、OC調用JS方法

UIWebView內置一個方式可以執行JavaScript代碼,因此OC調用JS比較方便點

- (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;

調用這個方法需要在網頁加載完成之后,因為這個時候整個html頁面包括js/css已經注入到webView中,此時調用方法才會有響應,相反網頁加載完成之前調用界面不會有任何響應

參考上圖,我們點擊小紅部分的事件按鈕,會調用JS中的事件處理代碼

OC部分:

    if (sender.tag == 123) {
        [self.webView stringByEvaluatingJavaScriptFromString:@"alertMobile()"];
    }
    
    if (sender.tag == 234) {
        [self.webView stringByEvaluatingJavaScriptFromString:@"alertName('小紅')"];
    }
    
    if (sender.tag == 345) {
        [self.webView stringByEvaluatingJavaScriptFromString:@"alertSendMsg('18870707070','周末爬山真是件愉快的事情')"];
    }

JS部分:

    function alertMobile() {
        alert('我是上面的小黃 手機號是:13300001111')
    }

    function alertName(msg) {
        alert('你好 ' + msg + ', 我也很高興見到你')
    }

    function alertSendMsg(num,msg) {
        alert('這是我的手機號:' + num + ',' + msg + '!!')
    }

  

二、JS調用OC方法

UIWebView加載過程中會有一系列代理方法,這里不關注其他的方法,只關注UIWebView在加載之前的一個代理方法

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;

這是UIWebView在加載之前或者網頁進行重定向的時候調用的一個方法,而我們JS調用OC采用協議攔截方式實現的細節就是在這個方法里面完成的

有了上面的方法后,很顯然,想要JS調用OC我們就可以采用在按鈕點擊的后重定向一個URL,這個URL攜帶OC的方法名及參數信息,然后在這個方法中拿到對應的URL,對URL進行解析,提取對應的方法名和參數信息,調用OC相應的方法,從而實現了交互的可能,下面是示例中的URL

rrcc://showSendNumber_msg_?13300001111&go climbing this weekend

在這個URL中前面的"rrcc://"是URL的scheme,通過這個來提取我們關心的URL,對其他URL不做任何處理,后面就是OC方法和參數的信息了,這里用"?"來分割分割方法名和參數,"&"來分割多個參數,"_"用作OC方法名中冒號的替換。如果你願意,可以使用任何幾個字符來定義這個規則,這里采用的URL中經常會見到的字符。下面貼出部分示例代碼

JS部分:

    function btnClick1() {
        location.href = "rrcc://showMobile"
    }

    function btnClick2() {
        location.href = "rrcc://showName_?xiaohuang"
    }

    function btnClick3() {
        location.href = "rrcc://showSendNumber_msg_?13300001111&go climbing this weekend"
    }

OC部分:

    NSArray *components = [subPath componentsSeparatedByString:@"?"];
    
    NSString *methodName = [components firstObject];
    
    methodName = [methodName stringByReplacingOccurrencesOfString:@"_" withString:@":"];
    SEL sel = NSSelectorFromString(methodName);

    NSString *parameter = [components lastObject];
    NSArray *params = [parameter componentsSeparatedByString:@"&"];
    
    if (params.count == 2) {
        if ([self respondsToSelector:sel]) {
            [self performSelector:sel withObject:[params firstObject] withObject:[params lastObject]];
        }
    }

  

三、含參數的方法調用

OC調用JS方法,如果有參數,直接在方面名后面的括號中寫入對應的參數即可;如果是含有多個參數,參數之間用","分開

JS調用OC方法,參數是攜帶在URL中,通過解析URL來調用對應的方法

 

四、原生UIWebView交互的優缺點

下面我們來分析下這種交互方式:

1. 由於OC執行選擇器(selector)方法的限制,這種方式最多只能傳遞參數的個數為2個,如果需要多個參數,(開個腦洞)可以從數據結構的組織方面入手

2. 每次需要發生交互的時候我們都需要來自定義一個URL,然后解析URL,最后提取參數,合成方法名,找到對應的方法來調用;如果項目中有幾十上百個地方需要交互來完成,這樣一一來寫的話,顯然不是聰明的辦法,到時候你的代碼也會是雜亂,難以維護的,所以這種交互方式適用於項目中有少量,極個別的地方需要交互的需求。

3. 我們嫌麻煩,前輩們肯定也會嫌麻煩,有沒有解決辦法呢?iOS7之前,蘋果沒有出 JavaScriptCore 之前,業界普遍采用開源庫WebViewJavascriptBridgeEasyJSWebView來解決的,原理都是基於攔截協議的封裝,采用率第一個要遠遠高於第二個,我們將在下一篇文章中介紹WebViewJavascriptBridge的具體使用方法

 

戳這里:本文的DEMO地址歡迎star

 


免責聲明!

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



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