1. 程式人生 > >Hybrid----優秀開原始碼解讀之JS與iOS Native Code互調的優雅實現方案

Hybrid----優秀開原始碼解讀之JS與iOS Native Code互調的優雅實現方案

轉載自:http://blog.csdn.net/yanghua_kobe/article/details/8209751

簡介

它優雅地實現了在使用UIWebView時JS與ios 的ObjC nativecode之間的互調,支援訊息傳送、接收、訊息處理器的註冊與呼叫以及設定訊息處理的回撥。

就像專案的名稱一樣,它是連線UIWebView和Javascript的bridge。在加入這個專案之後,他們之間的互動處理方式變得很友好。

在native code中跟UIWebView中的js互動的時候,像下面這樣:

[cpp] view plaincopyprint?
  1. //傳送一條訊息給UI端並定義回撥處理邏輯
  2.  [_bridge send:@"A string sent from ObjC before Webview has loaded." responseCallback:^(id error, id responseData) {  
  3.         if (error) { NSLog(@"Uh oh - I got an error: %@", error); }  
  4.         NSLog(@"objc got response! %@ %@", error, responseData);  
  5.  }];  

而在UIWebView中的js跟native code互動的時候也變得很簡潔,比如在呼叫處理器的時候,就可以定義回撥處理邏輯:

[javascript] view plaincopyprint?
  1. //呼叫名為testObjcCallback的native端處理器,並傳遞引數,同時設定回撥處理邏輯
  2. bridge.callHandler('testObjcCallback', {'foo''bar'}, function(response) {  
  3. <span style="white-space:pre">  </span>log('Got response from testObjcCallback', response)  
  4. })  

一起來看看它的實現吧,它總共就包含了三個檔案:

[plain] view plaincopyprint?
  1. WebViewJavascriptBridge.h  
  2. WebViewJavascriptBridge.m  
  3. WebViewJavascriptBridge.js.txt  

它們是以如下的模式進行互動的:


很明顯:WebViewJavascriptBridge.js.txt主要用於銜接UIWebView中的web page,而WebViewJavascriptBridge.h/m則主要用於與ObjC的native code打交道。他們作為一個整體,其實起到了一個“橋樑”的作用,這三個檔案封裝了他們具體的互動處理方式,只開放出一些對外的涉及到業務處理的API,因此你在需要UIWebView與Native code互動的時候,引入該庫,則無需考慮太多的互動上的問題。整個的Bridge對你來說都是透明的,你感覺程式設計的時候,就像是web程式設計的前端和後端一樣清晰。

簡單地羅列一下它可以實現哪些功能吧:

出於表達上的需要,對於UIWebView相關的我就稱之為UI端,而objc那端的處理程式碼稱之為Native端。

【1】UI端

(1)   UI端在初始化時支援設定訊息的預設處理器(這裡的訊息指的是從Native端接收到的訊息)

(2)   從UI端向Native端傳送訊息,並支援對於Native端響應後的回撥處理的定義

(3)   UI端呼叫Native定義的處理器,並支援Native端響應後的回撥處理定義

(4)   UI端註冊處理器(供Native端呼叫),並支援給Native端響應處理邏輯的定義

【2】 Native端

(1)   Native端在初始化時支援設定訊息的預設處理器(這裡的訊息指的是從UI端傳送過來的訊息)

(2)   從Native端向UI端傳送訊息,並支援對於UI端響應後的回撥處理邏輯的定義

(3)   Native端呼叫UI端定義的處理器,並支援UI端給出響應後在Native端的回撥處理邏輯的定義

(4)   Native端註冊處理器(供UI端呼叫),並支援給UI端響應處理邏輯的定義

UI端以及Native端完全是對等的兩端,實現也是對等的。一段是訊息的傳送端,另一段就是接收端。這裡為引起混淆,需要解釋一下我這裡使用的“響應”、“回撥”在這個上下文中的定義:

(1)   響應:接收端給予傳送端的應答

(2)   回撥:傳送端收到接收端的應答之後在接收端呼叫的處理邏輯

下面來分析一下原始碼:

WebViewJavascriptBridge.js.txt:

主要完成了如下工作:

(1) 建立了一個用於傳送訊息的iFrame(通過建立一個隱藏的ifrmae,並設定它的URL 來發出一個請求,從而觸發UIWebView的shouldStartLoadWithRequest回撥協議)

(2) 建立了一個核心物件WebViewJavascriptBridge,並給它定義了幾個方法,這些方法大部分是公開的API方法

(3) 建立了一個事件:WebViewJavascriptBridgeReady,並dispatch(觸發)了它。

程式碼解讀

UI端實現

對於(1),相應的程式碼如下:

[javascript] view plaincopyprint?
  1. /* 
  2.  *建立一個iFrame,設定隱藏並加入到DOM中 
  3.  */
  4.     function _createQueueReadyIframe(doc) {  
  5.         messagingIframe = doc.createElement('iframe')  
  6.         messagingIframe.style.display = 'none'
  7.         doc.documentElement.appendChild(messagingIframe)  
  8.     }  

對於(2)中的WebViewJavascriptBridge,其物件擁有如下方法:

[plain] view plaincopyprint?
  1. window.WebViewJavascriptBridge = {  
  2.         init: init,  
  3.         send: send,  
  4.         registerHandler: registerHandler,  
  5.         callHandler: callHandler,  
  6.         _fetchQueue: _fetchQueue,  
  7.         _handleMessageFromObjC: _handleMessageFromObjC  
  8.     }  

方法的實現:

[javascript] view plaincopyprint?
  1. <span style="white-space:pre">  </span>/* 
  2.      *初始化方法,注入預設的訊息處理器 
  3.      *預設的訊息處理器用於在處理來自objc的訊息時,如果該訊息沒有設定處理器,則採用預設處理器處理 
  4. 相關推薦

    Hybrid----優秀原始碼解讀JSiOS Native Code調優雅實現方案

    轉載自:http://blog.csdn.net/yanghua_kobe/article/details/8209751 簡介 它優雅地實現了在使用UIWebView時JS與ios 的ObjC nativecode之間的互調,支援訊息傳送、接收、訊息

    Flink-CEP論文原始碼解讀狀態狀態轉換

    Flink CEP的論文與設計 Flink的CEP設計與實現重度參考了論文《Efficient Pattern Matching over Event Streams》。下面我們就來結合論文談談Flink CEP的設計。 這篇論文探討的話題是如何在事件流

    Lumen開發:lumen原始碼解讀初始化(2)——門面(Facades)資料庫(db)

    緊接上一篇 $app->withFacades();//為應用程式註冊門面。 $app->withEloquent();//為應用程式載入功能強大的庫。 先來看看withFacades() /** * Register the facades

    Android hybridJSNative的通訊方式

    場景 為了降低開發成本和跨平臺一致性的使用者體驗.通常敏捷開發中通常採用混合型應用Hybrid App(Native View與WebView交替呼叫),而Js作為Html頁面中常用的邏輯處理指令碼,掌握JS和Java的相互通訊是非常重要的! 操作步驟

    【1】pytorch torchvision原始碼解讀Alexnet

    最近開始學習一個新的深度學習框架PyTorch。 框架中有一個非常重要且好用的包:torchvision,顧名思義這個包主要是關於計算機視覺cv的。這個包主要由3個子包組成,分別是:torchvision.datasets、torchvision.models、torchvision.trans

    以太坊原始碼探究交易簽名

    與比特幣相比,以太坊中的交易結構有相當明顯的不同。下面是以太坊中Transaction資料結構的UML圖:   以太坊交易類圖 右邊的txdata

    java原始碼解讀HashMap

    1:首先下載openjdk(http://pan.baidu.com/s/1dFMZXg1),把原始碼匯入eclipse,以便看到jdk原始碼            Windows-Prefe

    PyTorch原始碼解讀torch.utils.data.DataLoader(轉)

    原文連結 https://blog.csdn.net/u014380165/article/details/79058479 寫得特別好!最近正好在學習pytorch,學習一下! PyTorch中資料讀取的一個重要介面是torch.utils.data.DataLoade

    PyTorch原始碼解讀torchvision.models(轉)

    原文地址:https://blog.csdn.net/u014380165/article/details/79119664 PyTorch框架中有一個非常重要且好用的包:torchvision,該包主要由3個子包組成,分別是:torchvision.datasets、torchvision.mode

    PyTorch原始碼解讀torchvision.transforms(轉)

    原文地址:https://blog.csdn.net/u014380165/article/details/79167753 PyTorch框架中有一個非常重要且好用的包:torchvision,該包主要由3個子包組成,分別是:torchvision.dat

    jQuery原始碼解讀init函式

    jQuery的構造方法: // 直接new了一個物件。同時根據jQuery.fn = jQuery.prototype,jQuery.fn相當於jQuery.prototype。 jQuery = function( selector, context ) { return

    PyTorch原始碼解讀torchvision.transforms

    PyTorch框架中有一個非常重要且好用的包:torchvision,該包主要由3個子包組成,分別是:torchvision.datasets、torchvision.models、torchvision.transforms。這3個子包的具體介紹可以參考

    eureka原始碼解讀服務端

    剖析eureka服務端啟動流程 服務端啟動類-入口處 @EnableEurekaServer @SpringBootApplication public class EurekaServerApplication { public static void main(Strin

    Dubbo原始碼解讀動態代理

    前言 或許我們已悉知Java的動態代理的方式:jdk——通過介面中的方法名,在動態生成的代理類中呼叫業務實現類的同名方法;cglib——通過繼承業務類,生成的動態代理類是業務類的子類,通過重寫業務方法進行代理。dubbo在沿用java的jdk方式外,還採取了javassist方式——通過

    Lumen開發:lumen原始碼解讀初始化(1)——app例項

    先來看看入口檔案public/index.php //請求頭 header('Content-Type: application/json; charset=utf-8'); /* |-------------------------------------------------

    Spring原始碼解讀核心容器上節

    Spring架構圖 說明 Spring的流行程度就不用我來說了,相信大家如果使用JAVA開發就一定知道它。寫這篇文章的初衷在於:1.瞭解Spring底層實現原理,提升對Spring的認識與理解。2.學習優秀框架程式設計實現,學習優秀的設計模式。3.使用Spring三年多,對於底層細節希望知道更多,便於

    Spring原始碼解讀核心容器下節

    續 上一篇我們通過ClassPathXmlApplicationContext載入xml檔案,通過BeanFactory獲取例項bean的demo程式碼去解讀了Spring Core Container中的spring-beans,spring-core,spring-context三個元件之間的一些具體類

    Spark1.6-----原始碼解讀BlockManager元件shuffle服務和客戶端

    spark是分散式部署的,每個Task最終都執行在不同的機器節點上,map任務的輸出結果直接儲存到map任務所在的機器的儲存體系,reduce極有可能不再同一個機器上執行,所以需要遠端下載map任務的中間輸出。所以儲存系統中也包含ShuffleClient。 在BlockManager 176行

    Spark1.6-----原始碼解讀BlockManager的概述

    BlockManager的實現 BlockManager是spark儲存體系中的核心元件,Driver 和Executor都會建立BlockManager。 在SparkEnv 364行會建立BlockManager: // NB: blockManager is not val

    Spark1.6-----原始碼解讀TaskScheduler啟動

    必須啟動TaskScheduler才能讓他發揮作用 SparkContext 530行: _taskScheduler.start() 實際去調TaskSchedulerImpl 143行: override def start() { backend.start