首页 > 代码库 > wax lua 脚本升级练习(2)
wax lua 脚本升级练习(2)
wax lua 脚本升级练习(1)介绍了object-c通过调用lua中的函数计算两值乘积并返回显示。
这一篇将介绍通过点击按钮下载新的lua脚本文件,并且热加载lua,使起能即时生效。
在写代码前需要做一点点准备。
1.启动本机的Apache服务,作为新lua脚本的存放位置
打开“终端(terminal)”,输入sudo apachectl start(可能需要输入机器秘密),打开Safari浏览器地址栏输入 “127.0.0.1”,可以看到内容为“It works!”的页面.
其位于“/Library(资源库)/WebServer/Documents/”下,这就是Apache的默认根目录。
在这个目录下创建文件夹script,回头这个目录下存放新脚本。
( 停止:sudo apachectl stop 重启:sudo apachectl restart)
2.下载第三方库ZipArchive。用于解压从网络获取的脚本文件。
将ZipArchive.m,ZipArchive.h,crypt.h,ioapi.c,ioapi.h,mztools.c,mztools.h,unzip.c,unzip.h,zip.c,zip.h文件加载到工程中。
option+command+A 添加文件到工程,选中Copy items into destination group‘s folder ,点击Add。
这个时候运行程序可能会报错,因为有的文件不支持ARC。方法:
(工程->taggets->build Phases 可以看到Compile Sources里都是你工程中的类.m文件,双击你不使用ARC的文件, 输入 -fno-objc-arc )
- (IBAction)downlodNewLua:(id)sender { [[luaMain shareInstance] ExecLua:@{@"cmd":LUA_EVENT_DOWNLOAD_NEN_SCRIPT, @"param":@{}}]; }
luaCallBak.m
#import "luaCallBak.h" @implementation luaCallBak + (luaCallBak*) shareInstance{ static luaCallBak* _this = nil; static dispatch_once_t onceTokenInit; dispatch_once(&onceTokenInit, ^{ _this = [[luaCallBak alloc] init]; }); return _this; } - (NSString *) temdir { NSString * tem= NSTemporaryDirectory(); return tem; } - (NSString * )DocumentsDir { return [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]; } @end
修改main.lua文件的exeLuaCode函数
function exeLuaCode( param ) -- body print('exeLuaCode') if (not param) then return nil; end local dict_param = wax.json.parse(param); if dict_param then local cmd = dict_param['cmd']; if cmd == '10000' then return multiply(dict_param['param']) elseif cmd == '10001' then updateScriptStatus()--下载新脚本 end end end
local Script_URL ='http://192.168.1.102/script/new_script.zip';--新脚本文件的网络地址 function updateScriptStatus() -- body wax.http.request{Script_URL, format = 'binary', callback = function ( retvalue, retresponse ) -- body local ret_obj2 = retvalue;--通过网络地址下载下来的二进制文件内容 if retresponse and retresponse:statusCode() == 200 and ret_obj2 then printLog('start UnZip') if not scriptUnZip(ret_obj2) then --将二进制文件内容解压 return; end printLog('start move Script') if not moveTemScriptToScript() then--移动新脚本到固定位置 return; end reload_script_files();--加载新脚本 else printLog('request err') end end} end function scriptUnZip(zipdata) -- body local tmp_dir = luaCallBak:shareInstance():temdir();--调用oc的temdir函数,获取存放临时文件的临时路径 local temPath = tmp_dir ..'/video_analyze_script'; local scriptUpdateDir = tmp_dir local zipfile = scriptUpdateDir .. '/download_video_analyze_script'; zipdata:writeToFile_atomically(zipfile, 0);--将内存中的二进制内容写成临时文件 local bexist = NSFileManager:defaultManager():fileExistsAtPath(zipfile);--检查文件写成功否 if not bexist then printLog('zipfile failed'); return; end -- unzip file 解压文件到temPath目录 local ziparchine = ZipArchive:init(); if not ziparchine then printLog('ziparchine nill'); return; end if not ziparchine:UnzipOpenFile(zipfile) then printLog('open zip file failed'); return; end if not ziparchine:UnzipFileTo_overWrite(temPath, 1) then printLog('unzip file failed'); return; end ziparchine:UnzipCloseFile(); return 1 end --移动脚本搞这么复杂,是防止脚本移动过程中出错。影响现有脚本工作 function moveTemScriptToScript() -- body --printLog('moveTemScriptToScript') local scriptDir = luaCallBak:shareInstance():DocumentsDir(); --scriptDir存放升级后脚本的路径 scriptDir = scriptDir .. '/video_analyze_script' local tmp_dir = luaCallBak:shareInstance():temdir(); local temPath = tmp_dir ..'/video_analyze_script'; local backScriptDir = temPath ..'_bak'; local fm =NSFileManager:defaultManager(); local b = nil; local bexist = NSFileManager:defaultManager():fileExistsAtPath(scriptDir);--检查该路径是否有脚本 printLog(scriptDir) printLog(bexist) if not bexist then b = fm:moveItemAtPath_toPath_error(temPath,scriptDir,nil);--没有脚本,将下载解压后的文件移动到scriptDir位置 else fm:removeItemAtPath_error(backScriptDir,nil);--移除现有脚本的备份的文件夹 b = fm:moveItemAtPath_toPath_error(scriptDir,backScriptDir,nil);--将现有脚本文件夹改名字,作为备份 if b then b = fm:moveItemAtPath_toPath_error(temPath,scriptDir,nil);--将下载解压后的文件移动到scriptDir位置 if b then fm:removeItemAtPath_error(backScriptDir,nil);--移动成功,移除现有脚本到备份文件夹 printLog('remove old ScriptDir') else fm:moveItemAtPath_toPath_error(backScriptDir,scriptDir,nil);--移动失败,将现有脚本到备份文件夹改为现有脚本文件夹名 end end end return b end function reload_script_files( ... ) -- body printLog( "[reload_script_files...]") local scriptDir = luaCallBak:shareInstance():DocumentsDir();--调用oc函数,获取Documents路径,用于存放新脚本 scriptDir = scriptDir .. '/video_analyze_script' --设置lua到环境变量,require 新脚本的时候用 local m_package_path = package.path printLog(m_package_path) if not string.find(m_package_path, 'video_analyze_script') then package.path = string.format("%s/?.lua",scriptDir) end printLog(package.path) package.loaded['main'] = nil require('main') printLog( "[reload_script_files...done]") return "reload ok" end
代码添加完成了。
downlodNewLua -》ExecLua -》exeLuaCode -》updateScriptStatus -》scriptUnZip-》moveTemScriptToScript-》reload_script_files
将main.lua压缩成zip文件,改名new_script.zip,然后存放到本机的/Library/WebServer/Documents/script目录下
然后将main.lua文件中multiply函数里的“*”改为“+”运行程序
点击“4*3=”按钮,输出7,日志打印
exeLuaCode multiply Multiplicand = 4 Multiplier = 3 7
点击“下载新脚本”,日志打印
exeLuaCode start UnZip 2014-08-02 21:36:39.820 WaxDemo[16316:60b] 1 entries in the zip file start move Script /Users/zhaoyan/Library/Application Support/iPhone Simulator/7.1/Applications/DCA2AC15-6DE7-4393-9565-345A182906E6/Documents/video_analyze_script true remove old ScriptDir [reload_script_files...] scripts/?.lua;scripts/?/init.lua;scripts/?.dat;?.lua;?/init.lua;?.dat; /Users/zhaoyan/Library/Application Support/iPhone Simulator/7.1/Applications/DCA2AC15-6DE7-4393-9565-345A182906E6/Documents/video_analyze_script/?.lua [reload_script_files...done]
再次点击“4*3=”按钮,输出12,日志打印
exeLuaCode multiply Multiplicand = 4 Multiplier = 3 12
成功!!!
这里有一个问题没有处理,重新打开程序后,加载的还是旧脚本,就是当关闭程序后再次打开程序,点击“4*3=”按钮,输出的还是7。