1. 程式人生 > >H5和Native通訊剖析(IOS篇)

H5和Native通訊剖析(IOS篇)

1. H5需要喚起Native分享元件把內容分享到其他App裡;
2. 當手機網路從3G切換到WIFI時,需通知H5展示更為清晰的商品圖片;

類似這樣的通訊場景很多,那麼如何實現H5和Native通訊呢?下面以IOS平臺,來進行剖析:

H5和Native的通訊,可以簡化為js和object-c兩種語言的通訊。

object-c呼叫js方法和js變數、方法注入

在IOS底層框架,提供了一個非常有用的API:stringByEvaluatingJavaScriptFromString,藉助於這個API,能夠實現object-c呼叫js方法以及js變數、方法的注入

在H5頁面定義了一個getInutName

的js方法:

function getInputName(){
    return "ok";
}

通過如下程式碼object-c就可以呼叫到H5定義的方法getInputName,並且把返回值賦值給returnvalue

NSString *returnvalue = [webView stringByEvaluatingJavaScriptFromString:@"getInputName()"];//ok

object-c還可以完成js方法和變數注入

NSString *network = @"'wifi'";
NSString *javascriptCommand = @"function test
(){return 'ok';};var network="; javascriptCommand = [javascriptCommand stringByAppendingString:network]; [webView stringByEvaluatingJavaScriptFromString:javascriptCommand];

這樣H5就可以使用test方法和network變數

object-c還可以讀取一個JS檔案,完成JS方法批量匯入

NSBundle *bundle = [NSBundle mainBundle];
NSString *filePath = [bundle pathForResource:@"WebViewJavascriptBridge.js" ofType:@"txt"];
NSString *
js = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; [webView stringByEvaluatingJavaScriptFromString:js];

js呼叫object-c方法

在IOS7及以下版本,目前js還無法直接呼叫object-c定義的API,但在Mac OSX,js已經可以呼叫object-c定義的API,詳細請見這裡,查閱了相關文件,在IOS8預覽版已支援類似Mac OSX的呼叫方式,有待驗證。

雖然無法直接呼叫object-c定義的API,但可以另闢蹊徑。

在H5頁面js執行以下2種操作,都會被H5所在的WebView捕獲,同時執行相關object-c程式碼。

1. 改變location.href

window.location.href = mytestscheme://callfunction/parameter1/parameter2?parameter3=value

2. 建立iframe,設定src,並插入到body節點

function execute(url) 
{
  var iframe = document.createElement("IFRAME");
  iframe.setAttribute("src", url);
  document.documentElement.appendChild(iframe);
  iframe.parentNode.removeChild(iframe);
  iframe = null;
}
execute("mytestscheme://callfunction/parameter1/parameter2?parameter3=value");

雖然以上兩種方法都可以達到通訊的目的,但是第1種方法,在某些場景會有問題,比如H5喚起Native分享元件時,同時進行監控打點(通過客戶段來實現打點),結果是執行了兩次改變location.href操作,但實際就會執行一次操作,保險起見,請採用iframe的方案。

這個時候WebView就可以監控到請求,並且做出相應響應:

- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
   NSURL *URL = [request URL]; 
   if ([[URL scheme] isEqualToString:@"mytestscheme"]) {
       // parse the rest of the URL object and execute functions
   } 
}

可能還會有疑問,某些場景需要進行回撥(如H5向Native獲取當前地理位置,拿到地理位置後,在當前頁面顯示),這個如何處理呢?

H5向Native獲取地理位置的請求,通過iframe方法就可以達到,Native把地理傳遞給H5,通過執行js方法並帶上地理位置,這個裡面關鍵點是如何正確進行回撥。有以下兩種方式:

  1. 設定iframe src的時候,把執行回撥函式名傳遞給native,src類似為mytestscheme://getLocation/callbackName,最後native執行callName js方法
  2. 同樣也是通過設定iframe src,但是src為 mytestscheme:onJsCall:callbackId:getLocation(url根據自己需要定義),native統一執行和H5約定的回撥函式,如runCallback,並且傳遞引數為callbackId和地理位置,JS內部建立一個物件對映,如下:

(function(){

    var Bridge = {
        callbacks:{},
        callbacksCount : 1,
        getCallbackId:function(callback){
            var hasCallback = callback && typeof callback == "function";
            if(callback.__jsbridgeId__){
                return callback.__jsbridgeId__;
            }
            var callbackId = hasCallback ? this.callbacksCount++ : 0;
            if (hasCallback) {
                this.callbacks[callbackId] = callback;
                callback.__jsbridgeId__ = callbackId;
                return callbackId;
            }   
        },
        ios:function(options){
            var callbackId = this.getCallbackId(opt.callback),
                    path,
                    src;
                    path = [opt.fn].concat(opt.param);
                    src =  "mytestscheme:onJsCall:" + callbackId+ ":" + encodeURIComponent(JSON.stringify(path));
        }
    };

    window.runCallback = function(callbackId,resultArray){
        try {
                var callback = Bridge.callbacks[callbackId];
                if (!callback) return;
                callback.call(this,resultArray);
            } catch(e) {}   
    }
})();

H5和Native通訊原理基本介紹完了,下面再從開發便利性和可維護性,談談如何封裝,安全控制,以及推薦下業界優秀類庫。

關於JSBridge

有移動端開發經驗的同學,對JSBridge應該不會陌生,藉助於它,能夠輕鬆讓H5和Native進行通訊,而且開發很簡單,JSBridge為H5和Native通訊提供了一套完整的解決方案。

JSBridge的流程圖

JSBridge架構圖

Bridge特點是把所有通訊相關程式碼進行封裝,包括js和object-c程式碼,同時暴露相關的API給H5進行呼叫,這樣好處可以在一個地方進行維護和升級,注意,這裡有個細節點,這個WebViewJavascript.js可以選擇直接打包在App裡面,或者每個頁面進行引用。

個人比較推薦直接打包App裡面,節省流量,這塊程式碼還是比較穩定的,目前微信採用這樣的方式,手淘則需要在頁面進行引用。

關於安全

考慮到各種域名下H5頁面會出現WebView裡,需考慮到不是所有Native API都可以開放給所有域名下的H5,需要進行一定許可權控制,比較可行的辦法是通過域名進行分級控制,有些API是全部開放,有些API只開放給某些域名的(白名單),白名單放到服務端,實現實時更新。

優秀開源類庫推薦

相關推薦

H5Native通訊剖析(IOS)

1. H5需要喚起Native分享元件把內容分享到其他App裡; 2. 當手機網路從3G切換到WIFI時,需通知H5展示更為清晰的商品圖片; 類似這樣的通訊場景很多,那麼如何實現H5和Native通訊呢?下面以IOS平臺,來進行剖析: H5和Native的通訊,可以簡化為js和object-c兩種語言的通訊

【quickhybrid】H5Native交互原理

forkey read ogre 混合 param bject void 總結 true 前言 Hybrid架構的核心就是JSBridge交互,而實現這個交互的前提是弄清楚H5和Native端的交互 本文主要介紹Native端(Android/iOS)和H5端(泛指前端)的

手把手教你搭建React Native 開發環境 - ios (React [email&#

由於之前我是h5的,沒接觸過ios和安卓, 也不瞭解xcode配置,所以 建議學reace-native之前還是先去了解一下ios和安卓開發環境搭建等問題。 環境下載及配置 nodejs:https://nodejs.org/en/download/ 設定淘寶映象 $ npm con

最近做的h5Native互動協議

為了js 比較 優雅地 和iOS和Android做互動。設計此文件。 基本協議 iOS通過Javascript Core注入appHandler方法。此方法只有一個引數 String. 所有的H5呼叫Native 都走這個方法。    

H5Android通訊容器BridgeWebView的使用

PS:如果覺得這個系列的每篇文章太長,那就直接看視訊吧 執行效果 使用步驟 1. 在project的build.gradle新增如下程式碼(如下圖) allprojects {

React Native (IOSAndroid) 支付寶微信支付整合實戰(微信IOS

序言:React Native無論是在社群和應用程度上,在國內外是十分廣泛和普及的。而支付寶和微信在支付模組上都有或多或少的支援,雖然沒有完整的Demo,不過在我做過一個相關整合的專案後,在此我把相關的步驟和方法總結出來和大家分享,希望能夠幫助大家少走彎路,快速整合。 微信

iOS]關於 App 混合(Hybrid)開發的優化,包括H5、Weex等(本博客主要針對 iOS 應用講解,但該思想同樣適用於Android)

color 數據 後臺 lib 新版 生成 下載地址 代碼 版本   我們知道混合開發,可以節省很多成本(時間成本,經濟成本等等),所以有很多公司比較鐘愛這種開發形式,今天所講的優化方式,也是我在我們公司的應用中實際用了的,而且我寫的這個優化的 SDK 已經開源到 gith

詳細剖析I2CSPI通訊協議的區別

原文連結:http://m.elecfans.com/article/610220.html 1. 概述I2C與SPI協議 IIC vs SPI現今,在低端數字通訊應用領域,我們隨處可見IIC (Inter-Integrated Circuit) 和 SPI (Serial

React Native 中為IOSAndroid設定不同的Style樣式,一套程式碼解決雙端顯示

React Native 開發中,大多數的元件都是IOS和Android通用的,包括大量的功能性程式碼,至少有80%以上的程式碼可以複用,而剩下的一些元件樣式/少量的程式碼會需要區分雙端,但是為了這少量的程式碼把IOS和Android完全區分這明顯不合適,程式碼複用性下降,程式碼維護量上升

React總結之七_Redux伺服器通訊

React元件訪問伺服器的方式 Redux架構下訪問伺服器的方式 一、React元件訪問伺服器 代理功能訪問API React元件訪問伺服器的生命週期 以顯示天氣預報為示例: 通過伺服器API獲得天氣情況資料 展示天氣情況資料 分兩個步驟完成:(1)

iOS 主動與native 通訊

flutter與Native互動是必不可少的,今天梳理一下,flutter監聽native訊息 大致流程 flutter註冊EventChannel flutter EventChannel監聽native訊息 native通過EventChannel傳送訊息 程式碼梳

react-native系列(1)入門:瞭解RN前景入門指引

React-Native是一門用於開發移動應用程式的開源技術。 隨著原生開發Android和IOS移動應用的成本越來越高,很多企業選擇使用跨平臺一站式開發的React-Native(簡稱RN)作為替代方案。在Facebook的引領下,國外很多大廠也紛紛使用RN來開發移動應用程式,構建出世界一

h5iOS原生互動,h5iOS互相傳值

前言 : h5和iOS原生互動,互相傳值,下面程式碼是完整的.M檔案  簡單實現h5和原生互動,互相傳值。 // //  ViewController.m //  原生-H5簡單互動 // //  Created by Mr Yang on 2018/7/23. //  C

iOS執行緒通訊程序通訊的例子(NSMachPortNSTask,NSPipe)

iOS執行緒間的通訊 iOS中,兩個執行緒之間要想互相通訊,可以使用:NSMachPort 下面是例子 #define kMsg1 100 #define kMsg2 101 - (void)viewDidLoad { [super vi

《React Native入門到放棄》——ios

學習記錄篇 : react native環境搭建 環境:windows xp系統 +vm虛擬機器+mac系統+xcode7.1 開始並不瞭解開發環境需要 隨意安裝了os 10.9、os 10.10的mac系統來玩 ,被坑慘了 一、前期工作 1.

iOS開發】H5Native互動之JSBridge技術

做過混合開發的很多人都知道Ionic和PhoneGap之類的框架,這些框架在web基礎上包了一層Native,然後通過Bridge技術使得js可以呼叫視訊、位置、音訊等功能。本文就是介紹這層Bridge的互動原理,通過閱讀本文你可以瞭解到js與ios及andro

iOS 系統架構常用框架 (iOS開發

(一)iOS的系統架構 iOS基於UNIX系統,iOS的系統架構分為四層,由上到下一次為:可觸控層(Cocoa Touch layer)、媒體層(Media layer)、核心服務層(Core Services layer)、核心作業系統層(Core OS layer),如

[Cordova]JSNative互動實現關鍵程式碼(iOS)

一、JS中定義的exec函式:define("cordova/exec", function(require, exports, module) 。關鍵實現程式碼如下:1.建立command物件,並且將

iOSH5native傳值或從H5跳轉到native

本部落格遷移來自:http://www.jianshu.com/users/465865c268ed/latest_articles 由於專案中H5頁面比較多,這幾天H5頁面中有個新需求:點選H5頁面

Android native codeJavascript通訊

如果android和js互動的話,那就是要通過一個控制元件WebView。如果js要調android中方法的話,要通過JavascriptInterface,百度一下就能看到很多資料,這裡不詳述。 在API17之前的話,是不需要加@JavascriptInte