我先來(lái)拋一個(gè)??,為啥蘋(píng)果大大會(huì)禁用JSPatch的“熱更新”抓狭?以及iOS統(tǒng)計(jì)現(xiàn)階段可以通過(guò)審核的“熱更新”否过。
這個(gè)磚會(huì)在文中進(jìn)行探究和解答惭蟋。
首先,在那2017年3月8…煤伟,記得那是給女神過(guò)節(jié)的那一天便锨,蘋(píng)果爸爸大刀闊斧的砍向了JSPatch領(lǐng)銜的JS動(dòng)態(tài)代碼映射技術(shù)氨肌,頓時(shí)怎囚,感覺(jué)iOS熱更技術(shù)要變天恳守,之后類似各家大廠SDK中使用了JSPatch的都紛紛移除相關(guān)代碼讓開(kāi)發(fā)者進(jìn)行更新催烘,直到現(xiàn)在JSPatch發(fā)布的1.8.0版本公告中說(shuō)明都會(huì)大概率被拒,1.8.2的版本則在試驗(yàn)過(guò)程中:
但是為什么游戲中的熱更新技術(shù)不會(huì)受到蘋(píng)果的禁止考杉,作為一名技術(shù)人員崇棠,不討論其他角度的問(wèn)題,只從技術(shù)角度來(lái)看询刹,為什么 JSPatch蘋(píng)果認(rèn)為是不允許的凹联,而游戲引擎的熱更新技術(shù),蘋(píng)果認(rèn)為是可以的呢蔽挠?
其實(shí)就是JSPatch能夠?qū)λ械?Objective-C 的 API 進(jìn)行映射象泵,允許開(kāi)發(fā)者在 JS 端調(diào)用任意原生代碼,這會(huì)造成重大的安全隱患問(wèn)題朗涩。
游戲中的熱更新技術(shù)主要的實(shí)現(xiàn)方式是把動(dòng)態(tài)腳本下載之后谢床,讓動(dòng)態(tài)腳本調(diào)用游戲引擎提供的接口實(shí)現(xiàn)缺陷修復(fù)识腿。與 JSPatch不同的是造壮,動(dòng)態(tài)腳本并不能任意調(diào)用全部原生代碼耳璧,而是只能根據(jù)游戲引擎提供的接口調(diào)用相關(guān)功能旨枯。在這個(gè)過(guò)程中,游戲引擎的原生端作為一個(gè)安全沙箱皂贩,提供了一個(gè)安全的保護(hù)層,只要游戲引擎不要對(duì)外提供獲取通訊錄的接口婴栽,黑客就無(wú)法通過(guò)替換動(dòng)態(tài)腳本的方式獲取用戶的隱私資料居夹。進(jìn)而可以被認(rèn)為是安全的准脂,自然就不在蘋(píng)果的禁止范圍內(nèi)狸膏。
??總的來(lái)說(shuō):蘋(píng)果認(rèn)為JSPatch這個(gè)使用了dlopen(), dlsym(), respondsToSelector:, performSelector:湾戳,method_exchangeImplementations() 等反射函數(shù)動(dòng)態(tài)調(diào)用OC的API是危險(xiǎn)的砾脑,那現(xiàn)在iOS還有熱更新嗎韧衣,答案是肯定的,而且還不少购桑,但是大部分都是JS開(kāi)發(fā)的項(xiàng)目畅铭,這些項(xiàng)目肯定是可以熱更的,那iOS熱更有哪些呢勃蜘,哪些是原生的呢硕噩,接下來(lái)我們就探究一下“市面上的熱更新/熱修復(fù)”。??????(當(dāng)然缭贡,企業(yè)賬號(hào)就用JSPatch就可以了)
一炉擅、游戲類的熱修復(fù)
像老的cocos2dx和新的creater,還有u3d都用的lua腳本拉仍裙椤坑资;
二、阿里百川Fix
原生可接入的SDK穆端,這個(gè)條件是需要20萬(wàn)的日活袱贮,才會(huì)給SDK;
三、Weex嗽仪、RN兢孝、Hybrid等
本身由js編寫(xiě)的代碼,自然可以進(jìn)行js進(jìn)行bundle拉取
四窗轩、TTPatch、MangoFix等修復(fù)
https://github.com/yangyangFeng/TTPatch
https://github.com/YPLiang19/Mango
兩個(gè)方案原生可都接入
TTPatch:是JSPatch的一個(gè)簡(jiǎn)化版,用的是js的解釋器镀岛,支持的語(yǔ)法也比較全面卸留,底層原理和JSPatch是差不多的喳整,中間通過(guò)替換方法的方式,將目標(biāo)方法的IMP替換為_(kāi)objc_msgForward熬尺,直接開(kāi)始消息轉(zhuǎn)發(fā),然后在經(jīng)過(guò)resolveInstanceMethod 、forwardingTargetForSelector、methodSignatureForSelector到forwardInvocation里獲取到執(zhí)行方法的invocation對(duì)象艺挪,之后進(jìn)行操作以及替換器钟,不支持swift熱修復(fù)(可以集成用于動(dòng)態(tài)添加類)。
MangoFix:是DSL即 “領(lǐng)域?qū)S谜Z(yǔ)言”穆役,用的是解析器進(jìn)行詞法韧拒、語(yǔ)法、語(yǔ)義檢查和分析,作者用到了libffi庫(kù)(用于高級(jí)語(yǔ)言之間的相互調(diào)用)進(jìn)行運(yùn)行時(shí)動(dòng)態(tài)創(chuàng)建C函數(shù),然后在創(chuàng)建的C函數(shù)中查找MangoFix腳本中方法并調(diào)用(這個(gè)用了類似dlsym的symdl進(jìn)行動(dòng)態(tài)調(diào)用函數(shù)颂鸿,
)栽渴,然后用剛剛創(chuàng)建的C函數(shù)替換原來(lái)Method的IMP指針并保留原有的IMP指針墅冷,?? y1u1這個(gè)方案確實(shí)不錯(cuò),在語(yǔ)法上類似OC語(yǔ)法辖佣,上手挺快,但缺點(diǎn)也很顯著凸郑,畢竟解析方式都是作者寫(xiě)的救氯,在語(yǔ)法上支持的不全面务嫡,比如rac的語(yǔ)法就很頭疼去扣,不支持swift熱修復(fù)(可以集成用于動(dòng)態(tài)添加類)或链。
??總結(jié)一下:游戲的熱修復(fù)指望不上,阿里和騰訊的SDK門(mén)檻點(diǎn)兒高令宿,Weex叼耙、RN筛婉、Hybrid這三種方案原生App只能看看爽撒,則最后的兩種方案原生可以集成使用扼褪,目前均可以上架闹究,筆者用的就是MangoFix做的小功能熱修復(fù)刻伊,如果沒(méi)有拉取到需要修復(fù)腳本可以不初始化熱修復(fù)模塊晨川,腳本信息加密然后拉取到沙盒后解密加載证九。
補(bǔ)充:使用stinger進(jìn)行aop的方案也可以實(shí)現(xiàn)熱修復(fù)/熱更新。
補(bǔ)充:flutter 官方聲明是暫時(shí)不支持熱更新的共虑,但是flutter支持web開(kāi)發(fā)愧怜,于是“flutter+web技術(shù)對(duì)接”這個(gè)熱更方案出來(lái)了,大致上是還是用js加載更新方案妈拌。
其他
說(shuō)明:
總結(jié)不對(duì)的地方歡迎糾正?? 拥坛,本文僅供用于學(xué)習(xí)參考。參考資料:
TTPatch :https://github.com/yangyangFeng/TTPatch
MangoFix :https://github.com/YPLiang19/Mango
MangoFix原理分析 :http://www.reibang.com/p/a6511c687eda
動(dòng)態(tài)調(diào)用&定義C函數(shù):http://www.reibang.com/p/92d4c06223e7
Unity3D游戲輕量級(jí)xlua熱修復(fù)框架 :https://www.cnblogs.com/SChivas/p/7893048.html