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?-
//傳送一條訊息給UI端並定義回撥處理邏輯
- [_bridge send:@"A string sent from ObjC before Webview has loaded." responseCallback:^(id error, id responseData) {
- if (error) { NSLog(@"Uh oh - I got an error: %@", error); }
- NSLog(@"objc got response! %@ %@", error, responseData);
- }];
而在UIWebView中的js跟native code互動的時候也變得很簡潔,比如在呼叫處理器的時候,就可以定義回撥處理邏輯:
- //呼叫名為testObjcCallback的native端處理器,並傳遞引數,同時設定回撥處理邏輯
- bridge.callHandler('testObjcCallback', {'foo': 'bar'}, function(response) {
- <span style="white-space:pre"> </span>log('Got response from testObjcCallback', response)
- })
一起來看看它的實現吧,它總共就包含了三個檔案:
- WebViewJavascriptBridge.h
- WebViewJavascriptBridge.m
- 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?- /*
- *建立一個iFrame,設定隱藏並加入到DOM中
- */
- function _createQueueReadyIframe(doc) {
- messagingIframe = doc.createElement('iframe')
- messagingIframe.style.display = 'none'
- doc.documentElement.appendChild(messagingIframe)
- }
對於(2)中的WebViewJavascriptBridge,其物件擁有如下方法:
[plain] view plaincopyprint?- window.WebViewJavascriptBridge = {
- init: init,
- send: send,
- registerHandler: registerHandler,
- callHandler: callHandler,
- _fetchQueue: _fetchQueue,
- _handleMessageFromObjC: _handleMessageFromObjC
- }
方法的實現:
[javascript] view plaincopyprint?- <span style="white-space:pre"> </span>/*
- *初始化方法,注入預設的訊息處理器
- *預設的訊息處理器用於在處理來自objc的訊息時,如果該訊息沒有設定處理器,則採用預設處理器處理
-
相關推薦
Hybrid----優秀開原始碼解讀之JS與iOS 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 hybrid之JS與Native的通訊方式
場景 為了降低開發成本和跨平臺一致性的使用者體驗.通常敏捷開發中通常採用混合型應用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