本項目提供的庫是基于XCode 8.0進行編譯的,如果想要要低于XCode 8.0上能夠成功編譯,需要進行庫的重新編譯,請根據下面的步驟實現:
LuaScriptCore中提供了LSCContext(Swift中為LuaContext)這個上下文對象類來維護整個Lua的環(huán)境,所以使用LuaScriptCore的第一步就是對Context進行初始化。如:
Objective-C中
LSCContext *context = [[LSCContext alloc] init];
Swift中
var _context : LuaContext = LuaContext();
初始化完畢后才能進行下面的各種操作。
原生層中要操作Lua中的變量或者方法,通常使用到的就是組織Lua腳本來進行一些列的Lua操作(LuaScriptCore屏蔽了Lua庫中的C Api,目的是讓代碼更加接近原生,使用起來更加得心應手),然后交由Context進行腳本的解析。如:
Objective-C中
[self.context evalScriptFromString:@"print('Hello World');"];
Swift中
_context.evalScript(script: "print('Hello World');");
對于一些耗時或者Lua無法實現的功能(如:手機設備的拍照),都可以考慮交由原生層來實現,然后提供接口讓Lua進行調用。如下面獲取手機設備信息的方法:
如果是Objective-C項目,在Objective-C代碼中定義方法
[self.context registerMethodWithName:@"getDeviceInfo" block:^LSCValue *(NSArray *arguments) {
NSMutableDictionary *info = [NSMutableDictionary dictionary];
[info setObject:[UIDevice currentDevice].name forKey:@"deviceName"];
[info setObject:[UIDevice currentDevice].model forKey:@"deviceModel"];
[info setObject:[UIDevice currentDevice].systemName forKey:@"systemName"];
[info setObject:[UIDevice currentDevice].systemVersion forKey:@"systemVersion"];
return [LSCValue dictionaryValue:info];
}];
如果是Swifit項目,則在Swifit代碼中定義方法
_context.registerMethod(methodName: "getDeviceInfo", block: { (arguments : Array<LuaValue>) -> LuaValue in
var info : Dictionary<String, String> = Dictionary<String, String>();
info["deviceName"] = UIDevice.current.name;
info["deviceModel"] = UIDevice.current.model;
info["systemName"] = UIDevice.current.systemName;
info["systemVersion"] = UIDevice.current.systemVersion;
return LuaValue(dictionaryValue: info);
});
在Lua代碼中調用方法
local tbl = getDeviceInfo();
有時候需要通過調用Lua中的方法來取得返回值(在原生層中只能取得一個返回值),然后再做后續(xù)的處理,例如:
在Lua代碼中有add方法的定義
function add (a, b)
return a+b;
end
如果是Objective-C項目,在Objective-C代碼中通過context調用Lua方法
LSCValue *value = [self.context callMethodWithName:@"add"
arguments:@[[LSCValue integerValue:1000],
[LSCValue integerValue:24]]];
NSLog(@"result = %@", [value toNumber]);
如果是Swift項目,在Swift代碼中通過context調用Lua方法
let retValue : LuaValue? = _context.callMethod(methodName: "add",
arguments: [LuaValue(intValue: 1000), LuaValue(intValue:24)]);
if (retValue != nil)
{
NSLog("result = %d", retValue!.intValue);
}
LSCContext(Swift中為LuaContext)所定義的方法都是全局的,有時候需要對一系列的方法進行一個包裝,希望這些方法都歸類在某個模塊下,一來方便根據模塊來劃分方法的功能,二來可以避免名稱的沖突。因此,可以使用LSCModule來對Lua的功能進行擴展。需要根據下面步驟實現:
下面例子定義了一個日志模塊,如:
在Objective-C代碼中定義LSCModule的子類
/**
* 日志模塊
*/
@interface LogModule : LSCModule
/**
* 寫入日志
*
* @param message 日志信息
*/
+ (void)writeLog:(NSString *)message;
@end
@implementation LogModule
+ (void)writeLog:(NSString *)message
{
NSLog(@"** message = %@", message);
}
@end
注冊模塊
[self.context registerModuleWithClass:[LogModule class]];
如果你的是Swift項目,則可以在Swift代碼中進行如下定義
class LogModule: LSCModule
{
static func writeLog(message : String) -> Void
{
NSLog("** message = %@", message);
}
}
然后注冊模塊
_context.registerModule(moduleClass: LogModule.self);
在Lua代碼中調用
LogModule.writeLog('Hello Lua Module!');
Lua中沒有明確的面向對象特性,LuaScriptCore提供了一個面向對象的擴展,Lua可以簡單地封裝類型,并且進行類型實例的使用。首先需要先注冊面向對象的模塊類LSCObjectClass(如果原生層有繼承于LSCObjectClass類的子類需要注冊時,該步驟可省略),如:
Objective-C中
[self.context registerModuleWithClass:[LSCObjectClass class]];
Swift中
_context.registerModule(moduleClass: LSCObjectClass.self);
注冊成功后,可以直接在Lua中定義類型,如:
Object.subclass("MyClass");
-- 重寫類型的初始化方法
function MyClass:init ()
print("MyClass instance initialize...");
end
-- 定義類型屬性
MyClass.property = 0;
local instance = MyClass.create();
print (instance.property);
上述代碼的subclass就是子類化對象方法,其接收一個類型名稱參數,調用后會創(chuàng)建一個對應名稱的類型。該類型擁有Object的所有特性。
對于Lua的類定義有如下設定:
- 所有類型的根類是Object,這個注冊LSCObjectClass后會有這個類的定義.
- 必須使用subclass方法來進行子類化,必須傳入一個有效并且不重復的類型名稱參數。
- 必須使用類型的create方法進行類對象的實例化。
- 類型中的方法(即類方法)都以.號進行調用,類實例中的方法都以:號進行調用。類型和實例的屬性都以.號進行訪問。
- 每個類中都有一個叫super的屬性來指代其父類型。
- 需要調用父類方法時,請使用"類型.super.method"方式進行調用,如:
MyClass.super.test();
。- 當類實例對象初始化時會觸發(fā)init方法,銷毀時會觸發(fā)destroy方法,可以通過重寫這些方法來進行一些額外的工作。
如果需要讓原生類直接映射到Lua中,按照下面步驟實現:
如在OC中有如下類型定義
@interface LSCTPerson : LSCObjectClass
@property (nonatomic, copy) NSString *name;
+ (NSString *)moduleName;
+ (void)printPersonName:(LSCTPerson *)person;
- (void)speak;
- (void)walk;
@end
@implementation LSCTPerson
+ (NSString *)moduleName
{
//變更導出的類型名稱
return @"Person";
}
+ (void)printPersonName:(LSCTPerson *)person
{
NSLog(@"Person name = %@", person.name);
}
- (void)speak
{
NSLog(@"%@ speak", self.name);
}
- (void)walk
{
NSLog(@"%@ walk", self.name);
}
@end
然后對該類型進行注冊:
[self.context registerModuleWithClass:[LSCTPerson class]];
在Swift中可以如下定義
class LSCTPerson: LSCObjectClass
{
static override func moduleName() -> String
{
return "Person";
}
static func printPersonName(p : LSCTPerson) -> Void
{
NSLog("%@", p.name);
}
var name : String? = nil;
func speak() -> Void
{
NSLog("%@ speak", name ?? "noname");
}
func walk() -> Void
{
NSLog("%@ walk", name ?? "noname");
}
}
然后對該類型進行注冊:
_context.registerModule(moduleClass: LSCTPerson.self);
注冊成功后,在lua中即可使用該類型:
local person = Person.create();
person:setName("vimfung");
person:walk();
person:speak();
Person.printPersonName(person);
更多建議: