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。

wax lua 脚本升级练习(2),布布扣,bubuko.com

时间: 2024-12-23 04:37:10

wax lua 脚本升级练习(2)的相关文章

wax lua 脚本升级练习(1)

当发现线上app某一功能出现bug,即使在技术上很快的做出了这一bug的补丁,但是因为AppStore上线审核漫长,这将在一段时间里,用户用的都是这个款带有已知bug的产品. 这种情况的一个解决办法就是通过Lua给app打补丁,因为Lua是脚本语言,将脚本放在服务器上,在程序启动的某个时机动态的从服务器上下载Lua代码,并在本地执行,就实现了动态替换app代码,从而快速的给app打补丁. 现在就做一个小练习,模拟一下. (1)功能就是点击"4 x 3 ="按钮,将4和3传到lua,然后

第二十三篇:在SOUI中使用LUA脚本开发界面

像写网页一样做客户端界面可能是很多客户端开发的理想. 做好一个可以实现和用户交互的动态网页应该包含两个部分:使用html做网页的布局,使用脚本如vbscript,javascript做用户交互的逻辑.当需求变化时,只需要在服务端把相关代码调整一下,用户即可看到新的内容(界面). 传统的客户端程序开发流程和网页开发可能完全不同. 首先是界面的布局,在老式的界面布局过程中,程序员先在界面上放好各种控件,然后需要自己通过相应的代码来维护界面在不同状态下控件的显示状态及位置.当界面中元素很多时,单纯布局

lua脚本之lua语言简介以及lua的安装

本博主不擅于进行文字创作,所以,相当一部分文字皆复制于其他博文.还希望能够得到谅解.  一.Lua语言简介 Lua是一个免费的开源软件,可以免费用于科研及商业.Lua具有一个专家团队在维护和升级,其设计旨在项目中扩展功能,因此其内核小而稳定.在游戏开发中,Lua在用户界面.游戏数据管理.实时游戏事件管理.游戏人工智能.创建功能原型等方面具有强大的支持.Lua不能直接访问数据库,但可以通过整合其他语言组件来访问数据库:对于一些耗时要求更高效率的工作,一般交给更加底层的语言去完成,Lua只是起到整合

Java中使用Lua脚本语言(转)

Lua是一个实用的脚本语言,相对于Python来说,比较小巧,但它功能并不逊色,特别是在游戏开发中非常实用(WoW采用的就是Lua作为脚本的).Lua在C\C++的实现我就不多说了,网上随便一搜,到处都是这方面的介绍,我想说的是如何在Java下使用Lua以提高编程效率.增强你的程序可扩展性. 首先,要在Java上使用Lua脚本,必须有关于Lua脚本解释器以及Java程序可以访问这些脚本的相关API,即相关类库.我使用的是一个叫做LuaJava的开源项目,可以在: http://www.keple

online_jf.lua --累计在线时间领取物品(积分)的lua脚本

原作者: ayase 8-27修正 修复首次使用后的红字不需要额外进数据库导入计分表,这lua全自动生成 --------------------------------------------------------------惯例写在前面: 写这玩意其实学习性更大于目的性..= =研究了两天晚上写的我人参中滴第一个lua脚本,居然还真给我写出来了,好感动由于写代码的基础基本是零 所以碰了N+N次壁 什么函数字母大小写还要区分  -- 闹哪样啊喂 因为这个原因我试了半个多钟才发现问题所在什么函

C程序与Lua脚本相互调用

Lua脚本是一种可用于C程序开发/测试的工具,本篇介绍一下C程序与Lua脚本如何进行相互调用,更加详细的操作参见<Programing in Lua>.本文分为3个部分:1.Windows环境下Lua的下载以及安装注意事项:2.Visual C++6.0中Lua的配置:3.C程序与Lua脚本相互调用实例. 1.Windows环境下Lua的下载以及安装注意事项 a.下载Lua for Windows,笔者用的版本是V5.1.4-35: b.上微软官网,下载Visual C++运行库——vcred

redis限速器设计(不使用lua脚本及事物)

公司有一个需求,需要集群中的机器每分钟发送固定个数请求到局域网以外的一台服务器,固定个数,是指集群中的所有机器发送的所有的请求加起来是一个固定的个数,这就需要一个分布式的限速器. 首先想到的就是使用redis中的incr方法,在redis的官方文档中寻找到了一个示例 FUNCTION LIMIT_API_CALL(ip) ts = CURRENT_UNIX_TIME() keyname = ip+":"+ts current = GET(keyname) IF current != N

Cocos Code IDE里xcode工程lua脚本更新

lua脚本修改后xcode需要clean重新编译才能更新,这个是xcode里的老毛病了,网上有一些脚本但不是针对Cocos Code IDE的工程目录的,这里列出 cocos2dx版本3.1 首先在 Xcode 里选中工程,右侧会显示工程的设置界面. 从设置界面选择 Build Phases 标签,然后点击右下角的 Add Build Phases 按钮,并选择"Add Run Script". 在新出现的 Run Script 栏中输入以下内容: _TARGET_BUILD_CONT

.net core中加载lua脚本的类库: MoonSharp

前言 MoonSharp是一个支持C#调用lua脚本的类库,支持.net, .net core, mono, unity,因此在.net core中也能够使用,而且加载和调用lua也很方便简单: 官网:http://www.moonsharp.org/ 源码:https://github.com/xanathar/moonsharp nuget:PM> Install-Package MoonSharp 使用 加载脚本 1 string scriptCode = @" 2 sum = 0