那些多余的話
在ios平臺的基礎框架中勿璃,代碼的直接動態(tài)部署一直是一個無法解決的問題擒抛,所以我們只能退而求其次,通過建立腳本語言和OC的bridge來實現(xiàn)動態(tài)更新的目標蝗柔。在這個方向上闻葵,wax-lua框架是第一個解決方案,但是隨著wax-lua作者的放棄維護癣丧,wax框架逐漸被降級為做補丁修復的工具槽畔。之后隨著objc語言的完善和SDK中JavaScriptCore(webkit)framework api的開放,另外一種腳本語言js以一種更為被蘋果認可的姿態(tài)進入了這個方向胁编,先有國外FaceBook發(fā)布的ReactNative框架厢钧,讓更多的前端開發(fā)者可以通過js語言完成可以毗鄰native效果的app,后有國內(nèi)騰訊的bang開源JSPatch嬉橙,專注于ios平臺Patch修復早直。
本人最近一直在維護公司內(nèi)部的的wax框架,也一直在探索ios熱更新方向上的新技術市框。先是wax框架的兼容64位維護霞扬,wax框架集成到產(chǎn)品后多個組件交叉使用runtime的bug修復;再是探索Tianium跨平臺JS框架;再到FaceBook出品開源的ReactNative框架喻圃;再到最后的JSPatch... 這些框架的源碼和Demo我都有涉及萤彩,從希望到失望...首先是自己維護的wax框架穩(wěn)健性不夠,特別是通過AOP+forward兼容64位后bug頻現(xiàn)斧拍,用作patch熱更新尚且能夠應付雀扶,但是想用來做組件動態(tài)部署成熟度還不夠。其次Tianium框架肆汹,關于jscore部分沒有開源不敢用愚墓,另外其bind oc api部分需要時刻跟進新版本的SDK是一個low點。 再其次是ReactNative框架昂勉,源碼我沒有怎么看浪册,但是我寫了一個稍微復雜的頁面,當圖片在同一個頁面加載較多的時候岗照,卡頓的現(xiàn)象特別明顯议经,讓我對js的效率產(chǎn)生了深深的懷疑。 JSPatch同樣是利用了forward消息轉(zhuǎn)發(fā)機制完成了js和oc的bind谴返,但是社區(qū)和框架成熟度仍然不夠煞肾。
最近阿里開源了增強版的wax框架,我連續(xù)看了兩天源碼嗓袱,對其增強部分的實現(xiàn)有了一個大致的了解籍救,也讓我對lua-bind的方案有了很大的信心。之前受Andfix android平臺熱更新框架思路的影響渠抹,自己很想在這條路上再繼續(xù)折騰一番:如果能夠把OC代碼通過一個轉(zhuǎn)換器轉(zhuǎn)化成lua代碼蝙昙,ios平臺的準直接動態(tài)部署應該是可以實現(xiàn)的。 所有的開發(fā)人員仍然用自己最熟悉的objc開發(fā)需求梧却,測試和發(fā)版奇颠,比較版本代碼的不同可以讓低版本的產(chǎn)品用戶使用高版本的功能。我們可以不按照版本發(fā)布放航,轉(zhuǎn)而按照模塊開發(fā)烈拒,所有的新需求和新運營方案都可以在不發(fā)版的情況推送給用戶。
Ali-Wax簡介
代碼地址:https://github.com/alibaba/wax.git
wax-lua 的語言優(yōu)勢:
- (1)自動垃圾回收:再也不用使用alloc广鳍,retain和release荆几;
- (2)代碼少:沒有頭文件,沒有static類型赊时、array常量吨铸、dictionary常量;
- (3)能夠使用任何一個framework祖秒,例如cocoa诞吱、UITouch舟奠、Fondation等肴掷,任何用oc寫的framework受裹,wax自動將其暴露給lua使用斤贰;
- (4)超級簡單的http請求: 和REST的web service一起交互使用维苔;
- (5)lua也有函數(shù)閉包,也就是所謂的blocks靶剑;
- (6)lua有內(nèi)置的Regex-like 模式匹配library;
相比原Wax框架:
- 64位支持;
- 線程安全暴浦;
- 其他一些特性:
- lua function 轉(zhuǎn)化成 oc block,
- 在lua中調(diào)用oc block晓锻,
- getting/setting 私有成員變量歌焦,
- 內(nèi)置通用的C函數(shù),
- 支持lua代碼debug砚哆;
在接下來的博客系列中独撇,我將結(jié)合Ali—Wax源碼,介紹如何實現(xiàn)這些增強特性的躁锁,敬請期待纷铣。下面我們先來看看如何使用和集成wax框架和其debug環(huán)境。
Ali-Wax的Podfile集成
Wax框架只是一個熱更新實現(xiàn)方案战转,我們用于具體的產(chǎn)品進行補丁修復或者功能組件發(fā)布還需要實現(xiàn)一個版本管理方案搜立。在實現(xiàn)版本方案的時候,肯定涉及到在wax框架上的功能定制槐秧,比如說補丁現(xiàn)場恢復功能等(這部分功能我會開源到我的fork代碼中)啄踊。另外我們現(xiàn)在用CocoaPods管理我們的代碼組件版本,為了方便各自的產(chǎn)品修復bug刁标,發(fā)放版本颠通。 我建議大家fork一份代碼到自己的github中,進行版本管理膀懈。
fork Ali-Wax: https://github.com/philonpang/wax.git
另外Ali-Wax框架中集成了lua的debug方案:mobdebug顿锰,位于wax/tools/mobdebug處,作者配置了Podspec启搂,可以直接pod到你的調(diào)試工程中撵儿。 這部分代碼也不會有什么變化,已建議作者單獨列一個git工程狐血,目前我放到了自己的git空間里淀歇,大家可以共享。
mobdebug: https://github.com/philonpang/mobdebug.git
這樣我們就可以在項目工程中通過Pofile直接集成wax框架和代碼調(diào)試環(huán)境了(當然你也可以通過path指向wax clone項目的本地)匈织;podifle如下:
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '6.0'
inhibit_all_warnings!
workspace 'WLDWaxService'
xcodeproj 'LDWaxService'
target :LDWaxService do
pod 'wax', :git => 'https://github.com/philonpang/wax.git'
pod 'mobdebug', :git => 'https://github.com/philonpang/mobdebug.git'
link_with 'LDWaxService'
end
Ali-Wax的luaDebug
作者通過編譯luasocket源代碼支持了lua代碼的ios環(huán)境調(diào)試浪默。作者剛發(fā)布的時候的調(diào)試環(huán)境也折騰了我很久牡直,我這里說一下我踩過的那些坑和注意事項。 官方調(diào)試安裝步驟見:
[https://github.com/alibaba/wax/tree/master/examples/LuaCodeDebug]
- download ZeroBraneStudio (lua代碼調(diào)試IDE纳决,直接git clone到本地)
- run ZeroBraneStudio: 進入ZeroBraneStudio/zbstudio文件夾碰逸,直接雙擊ZeroBraneStudio.app文件即可運行(將app拷貝到application中不能運行)
-
import lua code: click the 6th button
, choose your lua code's root directory
- start debug server: click Project->Start Debugger Server. (每次打開ZeroBraneStudio的時候,記得打開這個選項)
- run this code before you enter debug
wax_start(nil, nil);//must start before debug
extern void luaopen_mobdebug_scripts(void* L);
luaopen_mobdebug_scripts(wax_currentLuaState());
- add
require('mobdebug').start('YOUR_MAC_IP_ADDRESS')
to your lua code. if you use simulator'YOUR_MAC_IP_ADDRESS'
can be empty - launch your app阔加,when
require('mobdebug').start()
is invoked, ZeroBraneStudio's dock will become active, then you should add breakpoint. (這種情況下饵史,當你在模擬器中運行app后,會自動跳在ZeroBraneStudio中啟動lua文件中斷點下來)
坑1:import luaCode 的tip
官方截圖上看到的截圖是整個xcode工程的目錄胜榔,如果你import了整個工程胳喷,在目錄和文件較多的情況下,ZeroBraneStudio中的斷點是無效的夭织。
其實你只需要import存放lua文件的目錄即可吭露。
坑2:xcode工程中的lua代碼文件
xcode添加文件有兩種方式:Create groups 和 Create folder reference兩種。 按照前一種方式尊惰,你引入目錄的所有文件在運行時會被拷貝到“XX.app/”目錄下讲竿,而后面一種方式目錄會以引用方式加入,運行時文件仍然放在“XX.app/拷貝目錄/”下弄屡,而且當引入目錄中有新文件添加的時候题禀,不用再執(zhí)行一遍添加操作。
所以我們在本地調(diào)試代碼的時候膀捷,建議以第二種方式引入目錄投剥,這樣我們可以隨時在ZeroBraneStudio中添加文件(而不用在xcode工程中再進行一次add操作)進行調(diào)試。 但是執(zhí)行l(wèi)ua代碼中的require代碼行時担孔,會提示找不到對應的require文件江锨。這其實是lua 默認search 文件的路徑?jīng)]有設置照成的,所以我們需要設置lua的search路徑環(huán)境變量糕篇。 代碼如下:
#import "wax.h"
#import "wax_http.h"
#import "wax_json.h"
#import "wax_xml.h"
//設置lua的search路徑環(huán)境變量
NSString *patchPath = [[NSBundle mainBundle] pathForResource:@"patchDemo" ofType:nil];
NSString *pp = [NSString stringWithFormat:@"%@/?.lua;", patchPath];
setenv(LUA_PATH, [pp UTF8String], 1);
//啟動wax框架和debug環(huán)境
wax_start(nil, luaopen_wax_http, luaopen_wax_json, luaopen_wax_xml, nil);//must start
extern void luaopen_mobdebug_scripts(void* L);
void * p = wax_currentLuaState();
luaopen_mobdebug_scripts(p);
//運行啟動文件
wax_runLuaString("require('patch')");
完成以上步驟之后啄育,你就可以在你的項目工程中開心的調(diào)試lua代碼了。如下圖所示: