首页 > 代码库 > 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需要添加如下代码
- (IBAction)downlodNewLua:(id)sender {
    [[luaMain shareInstance] ExecLua:@{@"cmd":LUA_EVENT_DOWNLOAD_NEN_SCRIPT, @"param":@{}}];

}



添加一个新类luaCallBak,用于lua调用oc代码到接口

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



在main.lua文件的尾部添加如下内容


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。