本文来自于:
http://liuwei.so/post/2015/01/30/Wax-%E5%BF%AB%E9%80%9F%E5%85%A5%E9%97%A8.html
简介
Wax 是一个 Lua 与 Objective-C 桥接库。这意味着你可以在 Objective-C 中调用 Lua 代码,也可以在 Lua 中 调用 Objective-C 代码。
在 Lua 中访问 Cocoa 类
在 Lua(通过 Wax)中访问 Cocoa 类与原生 Objective-C 看起来差不多。
NSString -- 返回 NSString 类
UIView -- 返回 UIView 类
UITableView -- 这仅仅是一个语法糖,与下面的效果相同。
wax.class["UITableView"] -- 这个一个 Wax 的原生调用,有了上面的语法糖你也许不需要知道这种调用方式
Lua 中创建 Objective-C 对象
当你创建一个 Objective-C 的对象时不需要调用 alloc了,wax 会自行处理。
-- 不需要调用 alloc,retain 或者 release。
local view = UIView.initWithFrame(CGRect(0, 0, 100, 100))
Lua 中创建 Objective-C 的类
在 Lua 中创建 Objective-C 的类需要调用函数 waxCLASS{CLASS\_NAME, PARENT_CLASS}
。紧随其后的所有函数(在这个文件中)会自动作为实例方法添加到这个类中。
waxClass{"MyClass", NSObject}
protocol
-- 添加 protocols 按下面的方式
waxClass{"MyClass", NSObject, protocols = {"UITableViewDelegate", "UITableViewDataSource"}}
-- 记住!Protocols 需要使用字符串的形式添加,因为协议不是类。
Lua 中 Objective-C 函数调用
调用一个 Lua 函数使用大括号 {}
替代圆括号 ()
仅仅是当只有一个参数的时候的一个语法糖 。
waxClass{"MyClass", NSObject}
-- 和下面等价
waxClass({"MyClass", NSObject})
-- 省略圆括号看起来更加舒适,这就是我们省略它的原因。
对于 waxClass 函数,第一个参数必须是 `self`。这是 Wax 怎么模拟 Objective-C 的面向对象。
waxClass{"MyClass", NSObject}
-- 注意到第一个参数是 self... 这个参数会保持 `MyCalss` 实例对象的引用
function storeWords(self, words)
self.words = words
-- Wax 会在 self 对象里创建一个 `super` 的变量
-- 使用 `super` 调用对象的父类的方法
self.super:words(self)
end
Lua 中调用 Objective-C 方法
当你调用任何 Objective-C 方法时需要使用冒号 :
代替点,则会把调用这个方法的对象作为第一个参数传递给这个被调用的方法。
-- 在 Lua 中使用 `:` 调用一个方法 ...
UIApplication:sharedApplication()
-- ... 和下面这种方式等价
UIApplication.sharedApplication(UIApplication)
-- 所以我们使用 `:` 可以保持 DRY 原则(不懂自己去搜),提高可读性。
Lua 中调用多参数的 Objective-C 方法
如果 Objective-C 方法有多个参数,必须使用下划线 _
替代 Objective-C 中的冒号 :
。
在 Objective-C 中:
[UIAlertView initWithTitle:@"title" message:@"message" delegate:nil];
在 Wax 中:
UIAlertView:initWithTitle_message_delegate("title", "message", nil)
property
Wax 不支持 Objective-C 的 properties。Wax 仅支持 Lua 与 Objective-C 之间使用方法通讯。
someView.frame -- 这个姿势是错误地.
-- 你需要使用 getter/setter 方法
someView:frame()
someView:setFrame(someFrame)
添加成员变量
你可以使用点号 .
给 Objective-C 对象动态添加成员变量。不像冒号 :
操作符(被用来调用 Objective-C 的类或实例方法),点号 .
操作符为对象在 Lua 端动态创建成员变量(Objective-C 端的对象并不知道这种变量的存在)。这些成员在对象的生命周期内可以使用。
-- 在 Lua 中使用 `:` 调用方法:
local view = UIView:init()
view.someRandomVariable = "YEAH!"
-- 你可以给这个实例对象赋任何东西且会保留下来
Lua 对象与 Objective-C 对象相互转换
Wax 将会试图维护原生 Lua 中的 Objective-C 对象。反过来也一样,如果一个 Objective-C 方法有一个 NSString 参数,你可以给他传第一个 Lua 字符串。
local fileManager = NSFileManager:defaultManager()
local contents = fileManager:directoryContentsAtPath(".")
-- directoryContentsAtPath 返回一个数组, 但是 Wax 把他转为一个 Lua table
print(contents[1]) --> "info.plist"
-- NSDictionaries 转为 Lua tables
-- NSArrays 转为 Lua tables
-- NSStrings 转为 Lua strings
-- NSNumbers 转为 Lua numbers
有些时候你并不想把一个 Objective-C 对象转换为 Lua 对象,可以使用 toobjc
方法实现。
-- 如果你试图调用一个 NSString 方法, 将会失败:
local string = "a string"
string:capitalizedString()
-- 因为 string 将会转为 Lua 字符串
-- 使用 toobjc, 将会把 Lua 字符串转为 NSString
toobjc(string):capitalizedString()
枚举
枚举,比如 UITableViewStylePlain
,其实是硬编码。最常用在 APP_ROOT/wax/stdlib/enums.lua
中声明。希望将来有一个桥接支持枚举和结构体可以自动创建。
selector
传递 selector
,使用字符串就好。比如在 Objective-C 中使用 @selector(this:is:a:method)
,在 Wax 中会这样使用 this:is:a:method
。
结构体
Lua 中的结构体也是用比较 tricky 的方式实现的,常用的结构体都保存在 APP_ROOT/wax/wax-scripts/structs.lua
。可以很方便地按照下面的方式添加架构提到 structs.lua
文件中。
wax.struct.create("CGRect", "ffff", "x", "y", "width", "height")
-- 创建一个名称叫做 `CGRect` 的全局函数,带有4个 float 类型的参数。
-- 第二个参数 "ffff" 定义参数的类型.
local rect = CGRect(1, 2, 3, 4)
print(rect.x) --> 1
rect.x = 200
print(rect.x) --> 200