OC Hybrid 開(kāi)發(fā)數(shù)據(jù)雙向流向

OC之WebView 和原生 App 交互。

最近參加了很多面試,都問(wèn)到了關(guān)于 Hybrid 開(kāi)發(fā)。
我基本可以把 WebView 和 OC 之間的雙向交互的原理說(shuō)明白。
并且可以自己手動(dòng)的寫(xiě) js 代碼完成雙端的交互。
但由于,之前沒(méi)有用過(guò)類(lèi)似的混合開(kāi)發(fā)的框架,被面試官給一票否決了。
想想挺郁悶的。

我所理解的 Hybrid 開(kāi)發(fā)。

說(shuō)實(shí)在話,為什么要用 Hybrid 開(kāi)發(fā)模式?

  1. 可以動(dòng)態(tài)的更新界面,比如活動(dòng)等。App 端則基本不用做修改。
  2. HTML5可以寫(xiě)出很絢麗的界面。而使用 OC 原生的要寫(xiě)出這么絢麗的界面是一件很費(fèi)時(shí)費(fèi)力的過(guò)程。

說(shuō)白了,在界面表現(xiàn)靈動(dòng)性的方面,HTML5比原生的 OC 強(qiáng)大多了。代價(jià)也更小。這種情況對(duì)于 OC 一個(gè)純開(kāi)發(fā) App 界面的語(yǔ)言來(lái)說(shuō),不知道有什么想法。


從 WebView 到 OC 的數(shù)據(jù)流向。

WebView 本質(zhì)上就是一個(gè)內(nèi)置的瀏覽器。
瀏覽器的執(zhí)行過(guò)程簡(jiǎn)單來(lái)看:

  1. 請(qǐng)求 URL
  2. 服務(wù)器返回 HTML 數(shù)據(jù)
  3. 瀏覽器解析渲染 HTML + CSS
  4. 瀏覽器執(zhí)行 JS。

那么 WebView 如何跟原生的 OC 發(fā)生交互呢?
原理就在:當(dāng) WebView 這個(gè)瀏覽器發(fā)送 URL 請(qǐng)求的時(shí)候,在 OC 級(jí)別我們可以使用 WebView 的代理方法捕獲到這個(gè)信號(hào)。
**- (BOOL)webView:(UIWebView )webView shouldStartLoadWithRequest:(NSURLRequest )request navigationType:(UIWebViewNavigationType)navigationType

這個(gè)代理方法返回值是 BOOL 類(lèi)型。
返回 YES 表示,請(qǐng)求繼續(xù)往下走,該干嘛干嘛。
返回 NO 表示,截獲了這個(gè)請(qǐng)求,請(qǐng)不要往下走了。也就是說(shuō),URL 請(qǐng)求,壓根就沒(méi)有發(fā)布出去。

對(duì)于 WebView 到 App 之間的交互,就是通過(guò)這個(gè)代理方法來(lái)執(zhí)行的。

簡(jiǎn)單實(shí)現(xiàn):

  1. 在 HTML 中,鑲嵌一個(gè) A 標(biāo)簽,給 href 屬性設(shè)置一個(gè)目的是不跳轉(zhuǎn)到百度,而是被截獲的協(xié)議鏈接。
<a href='gqs://ccccc'>從瀏覽器到 OC</a><br />

當(dāng)點(diǎn)擊 WebView 中這個(gè) A 標(biāo)簽的時(shí)候,會(huì)發(fā)送 URL 請(qǐng)求。于是進(jìn)進(jìn)入到上面的那個(gè)代理方法。

在代理方法中,過(guò)濾需要截獲的請(qǐng)求。

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
    if ([request.URL.absoluteString containsString:@"gqs"]) {
        NSLog(@"%@",@"捕獲到了自定義協(xié)議");
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"這是標(biāo)題" message:@"瀏覽器到 OC 的通道打通了!" preferredStyle:UIAlertControllerStyleAlert];
        
        UIAlertAction *confirmAction = [UIAlertAction actionWithTitle:@"知道了!" style:UIAlertActionStyleCancel handler:nil];
        
        [alertController addAction:confirmAction];
        
        [self presentViewController:alertController animated:YES completion:nil];
        
        return NO;

    }
    // 正常的URL鏈接就讓它們繼續(xù)去執(zhí)行。
    return YES;
}

到此為止,WebView -> App 的流向就走通了。
原理一句話:App 通過(guò)代理方法,截獲 WebView 的請(qǐng)求,根據(jù)請(qǐng)求篩選,做一些響應(yīng)的事情。


從 App 到 WebView 的走向。

說(shuō)白了,就是一個(gè)方法。
webView stringByEvaluatingJavaScriptFromString:
這兒方法,就是在當(dāng)前的 HTML 中,插入一段 js 代碼。
你插入的是什么 js 代碼,WebView 就執(zhí)行什么代碼。

一個(gè)簡(jiǎn)單的業(yè)務(wù)場(chǎng)景:

用戶(hù)需要從聯(lián)系人列表中,選中一個(gè)聯(lián)系人號(hào)碼(App 端)。然后把這個(gè)號(hào)碼賦值給 WebView 的某個(gè) HTML 文本框里。

也就是數(shù)據(jù)走向 : App -> WebView

做法如下:

  1. 在 HTML 中,實(shí)現(xiàn)定義一個(gè)用戶(hù)顯示用戶(hù)號(hào)碼的 js 函數(shù)。
<html>
<head>
    <title> 標(biāo)題</title>
</head>
<body>
<a href='gqs://ccccc'>從瀏覽器到 OC</a><br />
用戶(hù)的電話號(hào)碼:<input type="text" id="userPhone" />
</body>
</html>

<script type="text/javascript">
    function showUserPhoneNum(phoneNum) {
        document.getElementById("userPhone").value = phoneNum;
    }

</script>
  1. 在 App 中,選擇了用戶(hù)手機(jī)號(hào)碼之后,調(diào)用 stringByEvaluatingJavaScriptFromString 將手機(jī)號(hào)碼傳遞到 WebView 的 Input id = userPhone 這個(gè)文本框上。
- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContactProperty:(CNContactProperty *)contactProperty {
    // NSArray<CNLabeledValue<CNPhoneNumber*>*>
    /**
     ] (
     "<CNLabeledValue: 0x618000275a00: identifier=E297F1F7-CAFC-4A9D-ABF8-F79DB4496C87, label=_$!<Mobile>!$_, value=<CNPhoneNumber: 0x61800022be00: countryCode=us, digits=8885555512>>",
     "<CNLabeledValue: 0x618000275d00: identifier=5E423897-5B64-4129-AF55-10B1B3153697, label=_$!<Home>!$_, value=<CNPhoneNumber: 0x61800022c280: countryCode=us, digits=8885551212>>"
     )
     */
    NSString *phoneNumber = [contactProperty.value stringValue];
    NSLog(@"%@",phoneNumber); // 拿到用戶(hù)的電話號(hào)碼
    
    
    [self.webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"showUserPhoneNum(\"%@\")",phoneNumber]];
}

Hybrid 從 App-> 瀏覽器.gif

從 App -> WebView 原理:一句話,通過(guò)stringByEvaluatingJavaScriptFromString調(diào)用 HTML 中已經(jīng)寫(xiě)好的,或者自己寫(xiě)的 js 代碼,來(lái)實(shí)現(xiàn)App -> WebView 的數(shù)據(jù)走向。

DEMO 地址

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容