iOS OS X平臺文檔

2018-01-18 12:04 更新

集成說明

  1. 下載源碼到本地
  2. 打開Release目錄,如果您的是OC項目,可根據需要運行系統(tǒng)選擇iOS或者OSX目錄;如果您的是Swift項目,則可以根據運行系統(tǒng)選擇iOS-Swift或者OSX-Swift目錄
  3. 直接拖動目錄到XCode的工程下進行導入,導入時記得勾選"Copy items if needed"。
  4. 導入成功后則可以正常使用LuaScriptCore了。

關于重新編譯的問題

本項目提供的庫是基于XCode 8.0進行編譯的,如果想要要低于XCode 8.0上能夠成功編譯,需要進行庫的重新編譯,請根據下面的步驟實現:

  1. 打開Source/iOS_OSX/目錄中的LuaScriptCore項目文件。
  2. 選擇你想要重新編譯的平臺,如果是iOS的OC版本則選擇LuaScriptCore-iOS-output的scheme,Swift版本則選擇LuaScriptCore-iOS-Swift-output的scheme;如果是OS X的OC版本則選擇LuaScriptCore-OSX-output的scheme,Swift版本則選擇LuaScriptCore-OSX-Swift-output的scheme。
  3. Command + B 進行重新編譯,編譯后的庫文件和頭文件會放到Release目錄下替換原有的文件。

使用說明

初始化LuaScriptCore

LuaScriptCore中提供了LSCContext(Swift中為LuaContext)這個上下文對象類來維護整個Lua的環(huán)境,所以使用LuaScriptCore的第一步就是對Context進行初始化。如:

Objective-C中

LSCContext *context = [[LSCContext alloc] init];

Swift中

var _context : LuaContext = LuaContext();

初始化完畢后才能進行下面的各種操作。

解析Lua腳本

原生層中要操作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無法實現的功能(如:手機設備的拍照),都可以考慮交由原生層來實現,然后提供接口讓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方法

有時候需要通過調用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的功能進行擴展。需要根據下面步驟實現:

  1. 新聲明一個模塊類繼承于LSCModule類(必須繼承于LSCModule類,否則無法進行模塊注冊)
  2. 在創(chuàng)建的模塊類中定義需要導出到lua的類方法(即+號方法,注:-號方法是不會進行導出),聲明方法完全跟Objective-C/Swift的方法一樣(對于不想導出到Lua的方法可以在定義是使用下劃線“_”開頭),但需要注意的是結構體是無法作為參數或者返回值與Lua進行交互。
  3. 調用LSContext的registerModuleWithClass方法(Swift中調用LuaContext的registerModule方法)將定義的類型傳入即完成功能模塊的擴展。

下面例子定義了一個日志模塊,如:

在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面向對象

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的類定義有如下設定:

  1. 所有類型的根類是Object,這個注冊LSCObjectClass后會有這個類的定義.
  2. 必須使用subclass方法來進行子類化,必須傳入一個有效并且不重復的類型名稱參數。
  3. 必須使用類型的create方法進行類對象的實例化。
  4. 類型中的方法(即類方法)都以.號進行調用,類實例中的方法都以:號進行調用。類型和實例的屬性都以.號進行訪問。
  5. 每個類中都有一個叫super的屬性來指代其父類型。
  6. 需要調用父類方法時,請使用"類型.super.method"方式進行調用,如:MyClass.super.test();。
  7. 當類實例對象初始化時會觸發(fā)init方法,銷毀時會觸發(fā)destroy方法,可以通過重寫這些方法來進行一些額外的工作。

如果需要讓原生類直接映射到Lua中,按照下面步驟實現:

  1. 定義一個新的類繼承于LSCObjectClass類。
  2. 定義新類型的屬性和方法(注:原生類中的屬性會轉換為Lua類中的setXXX和XXX方法),對于不想導出到Lua中的方法或屬性可以在聲明時使用下劃線“_”開頭。
  3. 定義類的類方法會導出給類型,定義實例方法會導出給類型的實例。
  4. 調用LSContext的registerModuleWithClass方法(Swift中調用LuaContext的registerModule方法)將定義的類型傳入即完成Lua類的聲明。導入時可以直接導入子類,LSContext(或LuaContext)會檢測是否有導入根類型。

如在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);
以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號