iOS老司機的跨端跨平臺Hybrid開發Tips

語言: CN / TW / HK

本文正在參加「金石計劃 . 瓜分6萬現金大獎」

前言

  • Native與H5的混合開發是目前大前端繞不開的技術點, 在實際業務場景中有各種各樣的應用
  • 很多一線開發同學都會使用Hybrid混合開發中的各種技術及API, 去完成各種相互呼叫的需求
  • 知其然, 知其所以然. 作為一個有追求的大前端從業者, 我們一起來探究一下iOS中的Hybrid混合開發的前世今生.
  • 文章純手打, 拋磚引玉, 如有錯誤還請評論區指正, 先行謝過了:)

1. 原生與前端互動

1.1 什麼是JavaScriptCore?

  • JavaScriptCore 為原生程式語言 Objective-CSwift 提供呼叫 JavaScript 程式的動態能力,還能為 JavaScript 提供原生能力來彌補前端所缺能力。
  • 橋樑作用
  • JavaScriptCore,原本是 WebKit 中用來解釋執行 JavaScript 程式碼的核心引擎
    • 解釋執行 JavaScript 程式碼的引擎自 JavaScript 誕生起就有,不斷演進,一直髮展到現在
    • 如今蘋果公司有 JavaScriptCore 引擎、谷歌有 V8 引擎
    • iOS7 之前,蘋果公司沒有開放 JavaScriptCore 引擎。
    • 從 iOS7 開始,蘋果公司開始將 JavaScriptCore 框架引入 iOS 系統,並將其作為系統級的框架提供給開發者使用
  • JavaScriptCore 框架的框架名是 JavaScriptCore.framework

1.2 JavaScriptCore 框架的關鍵類分解剖析

  • JavaScriptCore 框架主要由 JSVirtualMachineJSContextJSValue 類組成。
  • JSVirturalMachine 的作用,是為 JavaScript 程式碼的執行提供一個虛擬機器環境。
    • JSContext 是 JavaScript 執行環境的上下文,負責原生和 JavaScript 的資料傳遞
      • JSValueJavaScript值物件,用來記錄 JavaScript 的原始值,並提供進行原生值物件轉換的介面方法

image.png

1.3 JavaScript 程式碼的 JavaScriptCore 和原生應用是怎麼互動的呢

  • JavaScriptCore 和原生應用要想互動,首先要有 JSContext

  • 除了 Block 外,我們還可以通過 JSExport 協議來實現在 JavaScript 中呼叫原生程式碼,

    • 也就是原生程式碼中讓遵循 JSExport 協議的類,能夠供 JavaScript 使用。

``` - (void)testJavaScriptCore {     // 建立JSVirtualMachine物件     JSVirtualMachine jsvm = [JSVirtualMachine new];     // 使用 jsvm的JSContext物件     JSContext ct = [[JSContext alloc] initWithVirtualMachine:jsvm];

//通過JavaScriptCore在原生程式碼中呼叫JavaScript變數     // 解析執行JavaScript指令碼     [ct evaluateScript:@"var i = 1 + 2"];

// 轉換"i"變數為原生物件     NSNumber *iNumber = [ct[@"i"] toNumber];     NSLog(@"var i is %@, iNumber is %@", ct[@"i"], iNumber);

// 解析執行 JavaScript指令碼     [ct evaluateScript:@"function subtraction(x, y) { return x - y }"];

// 獲得 subtraction 函式     JSValue *subtraction = ct[@"subtraction"];

// 傳入引數執行subtraction函式     JSValue *resultValue = [subtraction callWithArguments:@[@(3), @(1)]];

// 將 subtraction 函式執行的結果轉成原生NSNumber來使用     NSLog(@"function is %@, reusltValue is %@", subtraction, [resultValue toNumber]); } ``` image.png

1.4 iOS中Native和JavaScriptCore互動小結

  • 總的來說,JavaScriptCore 提供了前端與原生相互呼叫的介面,介面層上主要用的是 JSContextJSValue 這兩個類,
  • 通過 JSValueevaluateScript 方法、Block 賦值 contextJSExport 協議匯出來達到互通的效果。

2. Hybrid混合開發框架的幾個里程牌

2.1 基於JavaScript和WebView的跨平臺方案Cordova

  • Cordova的前身是PoneGap, 後被Apache收購, 成立Cordova專案組
  • Cordova的方案主要是通過H5來構建頁面, 再將其顯示在各個平臺的WebView中.
  • Cordova官方圖: image.png

2.1.1 Cordova的優缺點

  • Cordova的優點顯而易見, 背靠Apache這樣的大廠, 底層程式碼穩定, 文件清晰, 應用廣泛.
  • 但是它預設是不能呼叫Native的一些服務的(如相機、藍芽等硬體), 所以需要通過JavaScript進行橋接呼叫Native的一些API來完成某些基於硬體的功能.
  • 本身的使用者體驗、效能相對Native控制元件並不是太流暢, Native更新迭代的過程中容易產生很多適配問題.

2.2 久經考驗的React Native

  • React Native是Facebook在2015年4月開源出來的跨平臺開發框架, 是Facebook基於早先開源的JS框架React在原生移動應用平臺的衍生應用.
  • React Native使用JS語言, 類似於H5的JSX, 以及CSS來開發移動App, 降低了使用React框架的H5前端同學的學習成本.
  • 在保留基本渲染能力的基礎上, 用原生自帶的UI元件實現核心渲染引擎, 從而保證了良好的渲染效果.
  • 但是, 由於React Native的本質是通過JavaScript VM呼叫原生介面, 相對Native元件通訊較低效, 而且RN框架本身不負責渲染, 是間接通過原生進行渲染的.(參考大廠Airbnb由RN轉向Native.)

2.3 Google主推的跨平臺解決方案Flutter

  • Flutter使用Skia渲染引擎, 直接通過CPU、GPU進行圖形繪製, 不需要依賴任何Native控制元件.
  • Android作業系統中, 我們編寫的Native控制元件實際上也是依賴於Skia進行繪製渲染, 所以Flutter在某些Android小K做系統上, 甚至還要高於安卓原生(因為安卓原生中的Skia必須隨著作業系統進行更新, 二Flutter SDK中總是保持最新的Skia引擎).
  • 而類似於React Native框架, 必須通過橋接操作先轉成Native控制元件進行呼叫, 之後再進行渲染. image.png

3. 一些小結

  • 大前端中主流的3種跨平臺框架各有利弊, 選取哪個方案, 還是要由實際業務場景及專案具體情況決定.
  • 就像我們討論OOP POP FunctionalProgramming究竟是哪個好?
  • 最後還是MOP(Market Oriented Programming), 市場和具體業務情況決定了我們的技術選型, 應避免一味的炫技. 畢竟, 技術的成長和業務的發展是相輔相成的雙生:)

發文不易, 喜歡點讚的人更有好運氣👍 :), 定期更新+關注不迷路~

ps:歡迎加入筆者18年建立的研究iOS稽核及前沿技術的三千人扣群:662339934,坑位有限,備註“掘金網友”可被群管通過~

本文正在參加「金石計劃 . 瓜分6萬現金大獎」