iOS動態(tài)化之React Native

近段時間來,關(guān)于移動客戶端方面的動態(tài)化解決方案有了不少。之前的JSPatch,滴滴的解決方法:DynamicCocoa绊诲,微信iOS開發(fā)團(tuán)隊(duì)的解決方案:OCS。而今天需要說道的是React Native褪贵。

1. 背景

首先簡單介紹下滴滴和微信的解決方案掂之。

  • 1.1 DynamicCocoa
    DynamicCocoa 可以讓現(xiàn)有的 Objective-C 代碼轉(zhuǎn)換生成中間*代碼(JS),下發(fā)后動態(tài)執(zhí)行脆丁,相比其他動態(tài)化方案世舰,優(yōu)勢在于:

    • 使用原生技術(shù)棧:使用者完全不用接觸到 JS 或任何中間代碼,保持原生的 Objective-C 開發(fā)偎快、調(diào)試方式不變
    • 無需重寫已有代碼:已有 native 模塊能很方便的變成動態(tài)化插件
    • 語法支持完備性高:支持絕大多數(shù)日常開發(fā)中用到的語法冯乘,不用擔(dān)心這不支持那不支持
    • 支持 HotPatch改完 bug 后直接從源碼打出 patch,一站式解決動態(tài)化和熱修復(fù)需

    最重要DynamicCocoa有一下特點(diǎn):

    • 完整的 Class 定義:interface晒夹、category、class extension姊氓、method丐怯、property,最重要的是支持完備的 ivar 定義翔横,保持和 native 完全一致的實(shí)例內(nèi)存結(jié)構(gòu)
    • ARC:可以正確處理 strong读跷、weak、unsafe_unretained 等對象的引用計數(shù)禾唁,對象的 ivar 也可以正確的釋放
    • C 函數(shù):支持 C 函數(shù)的定義與 C 函數(shù)的調(diào)用效览、內(nèi)聯(lián)函數(shù)的調(diào)用
    • 可變參數(shù):支持 C 與 OC 的可變參數(shù)方法的調(diào)用无切,如 NSLog
    • struct:支持任意結(jié)構(gòu)體的使用,無需額外處理
    • block:支持創(chuàng)建和調(diào)用任意參數(shù)類型的 block
    • 其他 OC 特性:如 @selector丐枉、@protocol哆键、@encode、for..in 等
    • 其他 C 特性:支持使用宏瘦锹、static 變量籍嘹、全局變量,取地址等

    ps:DynamicCocoa完整介紹

  • 1.2 OCS
    OCS是全新設(shè)計的iOS動態(tài)化方案弯院。我們定義了一套精確描述OC語義的字節(jié)碼指令集(OCScript)辱士,開發(fā)了一套全自動編譯器(OCSCompiler),實(shí)現(xiàn)了一個高性能的虛擬機(jī)(OCSVM)以及一個可以跟底層無縫對接的橋接器(OCSBridge)听绳。我們首先使用OCS編譯器把OC源碼轉(zhuǎn)化成OCS字節(jié)碼颂碘,然后通過OCS橋接器實(shí)現(xiàn)OCS虛擬機(jī)與Native運(yùn)行時的互聯(lián),最后使用OCS虛擬機(jī)對OCS字節(jié)碼進(jìn)行解釋運(yùn)算椅挣,并驅(qū)動Native運(yùn)行時完成邏輯的執(zhí)行凭涂,以此達(dá)到Native代碼動態(tài)化的效果。OCS被用于iOS APP安裝包減包贴妻、功能插件化切油、HotPatch等方方面面動態(tài)化需求。

    • OCS有哪些與眾不同之處
      • 語義與OC保持嚴(yán)格一致
        OCS字節(jié)碼指令集語義與OC/的語義保持嚴(yán)格一一對應(yīng)關(guān)系名惩,支持的數(shù)據(jù)類型也完全等同澎胡,運(yùn)行過程無需進(jìn)行任何轉(zhuǎn)換,因此效率非常高娩鹉。
      • 自動化工具支持
        OCS擁有完善的自動化工具鏈攻谁,OCS編譯器支持絕大多數(shù)OC/C語法的轉(zhuǎn)化,包括C方法弯予、任意自定義結(jié)構(gòu)體戚宦、任意自定義block。對于少數(shù)不支持的的語法锈嫩,可以準(zhǔn)確報錯受楼,引導(dǎo)用戶進(jìn)行規(guī)避,避免產(chǎn)生未定義行為呼寸。OCS編譯器還可以準(zhǔn)確識別OC/C代碼的內(nèi)存管理語義艳汽,可以正確生成內(nèi)存管理相關(guān)的代碼。特別對于ARC來說对雪,可以準(zhǔn)確生成Retain河狐、Release代碼,正確插入到生成代碼中去。
      • 原生OC內(nèi)存管理機(jī)制
        OCS虛擬機(jī)完全支持Native的內(nèi)存管理機(jī)制馋艺,可以在正確的時機(jī)執(zhí)行正確的內(nèi)存釋放邏輯栅干,絕無延遲操作,徹底杜絕了Crash和爆內(nèi)存風(fēng)險的引入捐祠。
      • 搶占式多線程
        OCS虛擬機(jī)支持Native的搶占式多線程線程管理支持碱鳞,完全支持Pthread、 GCD雏赦、 NSOperationqueue劫笙、 NSThread等各種線程模型,完全避免了額外引入Crash星岗、卡頓與死鎖風(fēng)險填大。
      • 高性能匯編ABI
        OCS橋接器根據(jù)過程調(diào)用約定實(shí)現(xiàn)自定義OCSABI,使得虛擬機(jī)與Native底層實(shí)現(xiàn)直接通信俏橘,保證Native代碼動態(tài)化引入額外性能損耗最小化允华,使得OCS動態(tài)化不僅普遍適用于普通邏輯轉(zhuǎn)化,對于對性能要求苛刻的有復(fù)雜排版的滑動列表寥掐,OCS也有極佳的表現(xiàn)靴寂,動態(tài)化后掉幀率增長量幾乎可以忽略不計

ps:OCS完整介紹

  • 1.3 ReactNative
    React Native 讓開發(fā)者使用 JavaScript 和 React 編寫應(yīng)用,利用相同的核心代碼就可以創(chuàng)建 Web召耘,iOS 和 Android 平臺的原生應(yīng)用百炬。React Native 的宗旨是,學(xué)習(xí)一次污它,高效編寫跨平臺原生應(yīng)用剖踊。

    • React Native有什么優(yōu)點(diǎn)
      • 提供了原生的控件支持
        使用 React Native 你可以使用原生的控件,入在iOS平臺我們可以使用UITabBar控件衫贬,在Android平臺我們可以使用Drawer控件德澈。這樣,就讓我們的App從使用上和視覺上擁有像原生App一樣的體驗(yàn)固惯。而且使用起來也非常簡單梆造。

      • 異步執(zhí)行
        所有的JavaScript邏輯與原生的代碼邏輯都是在異步中執(zhí)行的。原生的代碼邏輯當(dāng)然也可以添加自己的額外的線程葬毫。
        這個特性意味著镇辉,我們可以將圖片解碼過程的線程從主線程中抽離出來,在后臺線程將其保存在磁盤中供常,在不影響UI的情況下計算調(diào)整布局等等摊聋。

        所以,這些讓React Native開發(fā)出來的App都是較為的流暢栈暇。
        這個之間的通信過程也是有序列化來完成的,這個就讓我們可以使用Chrome Developer Tools 來完成JavaScript邏輯的調(diào)試箍镜,當(dāng)然我們也能夠在模擬器和物理設(shè)備上調(diào)試源祈。

      • 觸屏處理 React Native實(shí)現(xiàn)了高性能的圖層點(diǎn)擊與接觸處理煎源。

      • Flexbox的布局樣式 使布局將變得更簡單,這就使我們?yōu)槭裁匆獙⒕W(wǎng)頁的布局模式切換到React Native的Flexbox布局模式香缺。Flexbox讓UI布局變得簡單手销,入使用margin和padding的嵌套模式。當(dāng)然图张,React Native 同樣也支持網(wǎng)頁原生的一些屬性布局模式锋拖,如FontWeight之類的。這些聲明的布局和樣式祸轮,都會存在內(nèi)聯(lián)的機(jī)制將其優(yōu)化兽埃。

      • Polyfills機(jī)制 React Native也支持我們使用第三方的JavaScript庫,來方便我們的開發(fā)适袜。支持npm中的成千上萬的模塊柄错。

      • 基于React JS 擁有React JS的優(yōu)良特性。

2. 抉擇

通過上面的簡單介紹苦酱,可以看出DynamicCocoa和OCS都還是很厲害的售貌。對于iOS開發(fā)人員,可以不需要去花費(fèi)過多的時間來學(xué)習(xí)其他語言疫萤,使用原生的Object-C也可以基本完成動態(tài)化颂跨。然后在實(shí)際開發(fā)中,以及實(shí)際的項(xiàng)目中扯饶,功能不僅僅是在iOS平臺上面恒削,同時在Android中也需要。這個時候就比較尷尬了帝际。但是ReactNative卻不一樣蔓同,他是跨平臺的,可以同時支持iOS和Android蹲诀,同時可以達(dá)到原生的效果(雖然和其他兩個的性能上還是有些差距)斑粱,而且現(xiàn)在的手機(jī)性能都在不斷提升,利弊權(quán)衡下脯爪,個人覺得ReactNative相對是更優(yōu)選擇则北。

3. ReactNative應(yīng)用

這里主要相對于現(xiàn)有工程

  • 3.1 在現(xiàn)有工程中添加ReactNative
    條件:
  • 1、CocoaPods
  • 2痕慢、Node.js

步驟:

  • 1尚揣、工程根目錄下創(chuàng)建ReactComponent
  • 2、在ReactComponent目錄中創(chuàng)建JS文件(例如:index.ios.js)掖举,并初始化
npm init
  • 3快骗、通過CocoaPods安裝ReactNative庫
def react_native
    # 取決于你的工程如何組織,你的node_modules文件夾可能會在別的地方。
    # 請將:path后面的內(nèi)容修改為正確的路徑(一定要確保正確~~)方篮。
    pod 'React', :path => ‘./ReactComponent/node_modules/react-native', :subspecs => [
    'Core',
    'ART',
    'RCTActionSheet',
    'RCTAdSupport',
    'RCTGeolocation',
    'RCTImage',
    'RCTNetwork',
    'RCTPushNotification',
    'RCTSettings',
    'RCTText',
    'RCTVibration',
    'RCTWebSocket',
    'RCTLinkingIOS',
    ]
end
  • 4名秀、執(zhí)行CocoaPods
pod install
  • 5、添加原生代碼
NSString * strUrl = @"http://127.0.0.1:8081/index.ios.bundle?platform=ios&dev=true";
    NSURL * jsCodeLocation = [NSURL URLWithString:strUrl];
    
    RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
                                                        moduleName:@"AwesomeProject"
                                                 initialProperties:nil
                                                     launchOptions:nil];
    self.view = rootView;
  • 6藕溅、運(yùn)行react
npm start
  • 7匕得、運(yùn)行原生應(yīng)用(Run)

4. ReactNative發(fā)布

在技術(shù)上來講當(dāng)然可以把react程序放在服務(wù)器上,但是加載速度就比較慢巾表,在用戶體驗(yàn)上當(dāng)然也會減分不少汁掠。因此可以通過打離線包(jsbundle)的方式,通過服務(wù)端控制來實(shí)現(xiàn)程序的動態(tài)化(類似JSPatch發(fā)布機(jī)制)。

  • ReactNative離線打包
    我們用‘react-native bundle’命令把JS代碼打包成一個bundle文件集币。然后客戶端直接訪問這個bundle文件即可考阱。
命令說明
react-native bundle

Options:

命令 枚舉 解釋
--entry-file index.ios.js 入口文件
--platform "ios"/"android" 平臺
--transformer /packager/transformer.js transformer
--dev false /true 調(diào)試開關(guān)
--prepack false/true
--bridge-config
--bundle-output 路徑 bundle包目標(biāo)路徑
--assets-dest 資源文件路徑 資源文件路徑
  • 修改原生代碼
NSURL * jsCodeLocation = [[NSBundle mainBundle ] URLForResource:@"main" withExtension:@"jsbundle"];
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation moduleName:@"AwesomeProject" initialProperties:nil launchOptions:nil];
self.view = rootView;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市惠猿,隨后出現(xiàn)的幾起案子羔砾,更是在濱河造成了極大的恐慌,老刑警劉巖偶妖,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件姜凄,死亡現(xiàn)場離奇詭異,居然都是意外死亡趾访,警方通過查閱死者的電腦和手機(jī)态秧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來扼鞋,“玉大人申鱼,你說我怎么就攤上這事≡仆罚” “怎么了捐友?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長溃槐。 經(jīng)常有香客問我匣砖,道長,這世上最難降的妖魔是什么昏滴? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任猴鲫,我火速辦了婚禮,結(jié)果婚禮上谣殊,老公的妹妹穿的比我還像新娘拂共。我一直安慰自己,他們只是感情好姻几,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布宜狐。 她就那樣靜靜地躺著势告,像睡著了一般。 火紅的嫁衣襯著肌膚如雪肌厨。 梳的紋絲不亂的頭發(fā)上培慌,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天豁陆,我揣著相機(jī)與錄音柑爸,去河邊找鬼。 笑死盒音,一個胖子當(dāng)著我的面吹牛表鳍,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播祥诽,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼譬圣,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了雄坪?” 一聲冷哼從身側(cè)響起厘熟,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎维哈,沒想到半個月后绳姨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡阔挠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年飘庄,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片购撼。...
    茶點(diǎn)故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡跪削,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出迂求,到底是詐尸還是另有隱情碾盐,我是刑警寧澤,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布揩局,位于F島的核電站毫玖,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏谐腰。R本人自食惡果不足惜孕豹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望十气。 院中可真熱鬧励背,春花似錦、人聲如沸砸西。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至衅疙,卻和暖如春莲趣,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背饱溢。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工喧伞, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人绩郎。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓潘鲫,卻偏偏與公主長得像,于是被迫代替她去往敵國和親肋杖。 傳聞我的和親對象是個殘疾皇子溉仑,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內(nèi)容