iOS 動態(tài)化熱修復(fù)方案

iOS 動態(tài)化熱修復(fù)方案

Warnning

純粹是技術(shù)分享我擂,不要用于上架操作约素!

前言

iOS熱修復(fù)方案經(jīng)過JSPatch事件后,也消停了很久。bang神在《JSPatch – 動態(tài)更新iOS APP》中曾提到硅急,為了更符合Apple的規(guī)則,即《Apple Developer Program License Agreement》 里3.3.2提到的不可動態(tài)下發(fā)可執(zhí)行代碼佳遂。
JSPatch特地繞了js的圈子营袜,從而實現(xiàn)曲線救國、實現(xiàn)熱更新的方案丑罪。但是事實證明了Apple對于這種方案也是不認可的荚板,根本的原因還是在于JSPath做得太過極致--支持絕大部分的OC/C語法凤壁。

思考

既然JSPatch繞道js的方法,已經(jīng)被Apple拒絕了跪另,那么就再次回到原點拧抖,重新出發(fā)。新的框架或者新的方案我覺得至少有一個充分條件免绿,就是不能太極致唧席。
Objective-C作為一種動態(tài)的語言,因此能夠動態(tài)執(zhí)行所有OC語法是正常的针姿,Aspects類似的框架也是被Apple認可的袱吆。至于是否需要運行所有的C函數(shù),這個有待商榷距淫。
第二個方面绞绒,則是放棄javascript/lua等類似語言作為更新的腳本,而是采用原生的Objective-C作為更新的腳本語言榕暇。

動態(tài)運行C函數(shù)

C語言是沒有反射機制的蓬衡,作為一門編譯型語言,在編譯期間就已經(jīng)生成機器碼彤枢。因此如果要從字符串中獲取到對應(yīng)的函數(shù)指針狰晚,那么大概有兩種方法:

  • 建立映射表, 將函數(shù)名和函數(shù)指針建立一個映射表。
  • dlsym, 根據(jù)動態(tài)鏈接庫操作句柄與符號缴啡,返回符號對應(yīng)的地址壁晒。

第二種是目前JSPatch采用的辦法,當然也被Apple警告了业栅。dlsym功能非常強悍秒咐,是獲取函數(shù)指針的最優(yōu)解。
第一種局限性非常大碘裕,但是沒有用到黑魔法携取。

采用Objective-C作為更新的腳本語言

通過flex/yacc,直接解析Objective-C語法帮孔,不再采取js/lua等腳本語言雷滋。

DynamicOC

經(jīng)過上面的思考,在最近業(yè)余中做了DynamicOC的項目,百分百原生支持采用Objective-C作為更新的腳本語言。
當然動態(tài)運行C函數(shù)還是采用dlsym獲取函數(shù)指針的辦法讯壶,后面會逐步改為映射表的做法懒构。

原理

DynamicOC使用flex/yacc進行詞法解析和語法分析,轉(zhuǎn)為一顆語法生成樹AST。
然后通過解析每個節(jié)點,從而執(zhí)行相應(yīng)的代碼。因為采用的是Objective-C作為腳本語言烹俗,因此極容易適配爆侣。

功能特點

  • 動態(tài)執(zhí)行OC代碼
  • 動態(tài)執(zhí)行C函數(shù)和block異步調(diào)用
  • 動態(tài)添加屬性
  • 動態(tài)替換方法
  • 動態(tài)添加方法
  • 有完善的單元測試
  • flex/yacc實現(xiàn)強大的OC語法解析器
  • 支持CGRect/CGSize/CGPoint/NSRange/UIEdgeInsets/CGAffineTransform常用結(jié)構(gòu)體
    ...

基本用法

動態(tài)執(zhí)行block

NSString* text = @" \
__block int result = 0;\
UIView* view = [[UIView alloc]init];\
void(^blk)(int value) = ^(int value){\
view.tag = value;\
};\
blk(1024);\
return view.tag;";

ASTNode* root = [ASTUtil parseString:text];
ASTVariable* result = [root execute];
NSAssert([result.value doubleValue] == 1024, nil);

動態(tài)執(zhí)行C函數(shù)

int echo(int value) {
return value;
}

NSString* text = @" \
[OCCfuntionHelper defineCFunction:@\"echo\" types:@\"int, int\"]; \
return echo(1024);";

ASTNode* root = [ASTUtil parseString:text];
ASTVariable* result = [root execute];
NSAssert([result.value doubleValue] == 1024, nil);

動態(tài)添加Property

NSString* text = @" \
[OCCfuntionHelper defineCFunction:@\"objc_setAssociatedObject\" types:@\"void,id,void *,id,unsigned int\"];\
[OCCfuntionHelper defineCFunction:@\"objc_getAssociatedObject\" types:@\"id,id,void *\"];\
NSString* key = @\"key\"; \
objc_setAssociatedObject(self, key, @(1024), 1);\
return objc_getAssociatedObject(self, key);";

ASTNode* root = [ASTUtil parseString:text];
ASTVariable* result = [root execute];
NSAssert([result.value doubleValue] == 1024, nil);

已支持語法

  • [x] if/else while do/while for
  • [x] return break continue
  • [x] i++ i-- ++i --i
  • [x] +i -i !i
  • [x] + - * / %等四則運算
  • [x] >> << & | ^ 等位運算
  • [x] && || >= <= != > < 等比較運算
  • [x] ?:
  • [x] __block
  • [x] array[i] dict[@""]
  • [x] @666 @() @[] @{}
  • [x] self super
  • [x] self.property
  • [x] self->_property
  • [x] most of objective-c keyword

TODO

  • [ ] @available()
  • [ ] [NSString stringWithFormat:"%d",value] : use [NSString stringWithFormat:"%@",@(value)] instead。
  • [ ] dispatch_async / dispatch_after ...
  • [ ] *stop =YES, in block
  • [ ] fix bugs

參考鏈接

JSPatch – 動態(tài)更新iOS APP
iOS 動態(tài)化的故事
Apple Developer Program License Agreement
滴滴 iOS 動態(tài)化方案 DynamicCocoa 的誕生與起航

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末幢妄,一起剝皮案震驚了整個濱河市兔仰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蕉鸳,老刑警劉巖乎赴,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異潮尝,居然都是意外死亡榕吼,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進店門勉失,熙熙樓的掌柜王于貴愁眉苦臉地迎上來羹蚣,“玉大人,你說我怎么就攤上這事乱凿⊥缢兀” “怎么了?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵徒蟆,是天一觀的道長胁出。 經(jīng)常有香客問我,道長段审,這世上最難降的妖魔是什么全蝶? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮寺枉,結(jié)果婚禮上抑淫,老公的妹妹穿的比我還像新娘。我一直安慰自己型凳,他們只是感情好丈冬,可當我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布嘱函。 她就那樣靜靜地躺著甘畅,像睡著了一般。 火紅的嫁衣襯著肌膚如雪往弓。 梳的紋絲不亂的頭發(fā)上疏唾,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天,我揣著相機與錄音函似,去河邊找鬼槐脏。 笑死,一個胖子當著我的面吹牛撇寞,可吹牛的內(nèi)容都是我干的顿天。 我是一名探鬼主播堂氯,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼牌废!你這毒婦竟也來了咽白?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤鸟缕,失蹤者是張志新(化名)和其女友劉穎晶框,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體懂从,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡授段,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了番甩。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片侵贵。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖对室,靈堂內(nèi)的尸體忽然破棺而出模燥,到底是詐尸還是另有隱情,我是刑警寧澤掩宜,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布蔫骂,位于F島的核電站,受9級特大地震影響牺汤,放射性物質(zhì)發(fā)生泄漏辽旋。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一檐迟、第九天 我趴在偏房一處隱蔽的房頂上張望补胚。 院中可真熱鬧,春花似錦追迟、人聲如沸溶其。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瓶逃。三九已至,卻和暖如春廓块,著一層夾襖步出監(jiān)牢的瞬間厢绝,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工带猴, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留昔汉,地道東北人。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓拴清,卻偏偏與公主長得像靶病,于是被迫代替她去往敵國和親会通。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,446評論 2 348

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