Loc Library provides a bridge of type conversion between Lua and Objective-C. It handles type conversion and function reflection, hence we can simply reqeust Objective-C property, call Objective-C function in Lua with Lua syntax.
Values of types listed below are copied to the corresponding types on conversion in each direction. For userdata type, Loc will register metatable for the relative Objective-C type to reflect Lua methods to instance methods.
Objective-C type | Lua type |
---|---|
nil | nil |
NSNull | nil |
NSString | string |
NSNumber | number, boolean |
NSDictionary | table, userdata |
NSArray | table, userdata |
NSObject | userdata |
Class | userdata |
If we want to use Loc in project, we just call following method to register Loc Library to lua_State
:
loc_registerlib(L);
Now we are good to play Objective-C in Lua.
Loc extends NSObject with - (BOOL)pushToLuaState:(lua_State *)L
via Category, so we can call this function to push object to stack of given lua_State
[obj pushToLuaState:L];
If obj
is nil
, it pushes nothing to stack, which may causes problem, so it is recommended to call following method to push object, if object may be nil:
loc_pushid(L, obj);
The reset process is the same as working with other type (e.g.: string, number, boolean) which is pushed to stack. We can set value to global with void lua_setglobal (lua_State *L, const char *var)
, or call a Lua function with the object as arguments.
Loc provides similar "to" method as lua_tostring
,
lua_tonumber
in Lua, to fetch object from Lua stack:
id loc_toid(lua_State *L, int idx)
The method automatically returns associated NSObject instance base on above table.
If we want to gurantee the value is not primitive, which must be Objetive-C object, we could use similar "check" method:
id loc_checkuserdata(lua_State *L, int idx);
id loc_checkclass(lua_State *L, int idx, Class clazz);
NSString *loc_checkstring(lua_State *L, int idx);
We can also compulsorily convert Lua table to NSArray or NSDictionary:
NSArray *loc_toarray(lua_State *L, int idx);
NSDictionary *loc_todictionary(lua_State *L, int idx);
When we want to get propety value of object, we can use colon(:) syntax, and give property name, and call it as function:
local name = obj:name();
dot(.) syntax does not work to access the property.
We can pass new value to property function to set value on it with colon(:) syntax:
obj:name('newName');
We can also use dot(.) syntax to assign new value directly to property:
obj.name = 'newName';
Getting property is almost the same as call method of object if the method does not have argument. For methods with arguments, Objetive-C method seperate method name into multiple parts, and use colon(:) to delimit name and arguments. The method name use in Lua should be the concatenation of all parts, captalize the character right after colon, remove all colons.
For example, if we define a method in Objective-C like:
- (void)printBool:(BOOL)b string:(NSString *)s andArray:(NSArray *)a
In lua we call as:
obj:printBoolStringAndArray(true, 'Hello World', arrObj);
If method has return value, we can assign to variable, or pass it to other method as arguments
local sum = obj:addAWithB(21, 7);
ATTENTION: function call should use colon(:) syntax like getting property
Loc does some specialization for NSDictionary
and NSArray
, as they are Objective-C system collection, and used very often. Intead of use NSInvocation
to reflect method call, Loc direct map methods.
NSDictioanry
Lua Syntax | Mapped Call |
---|---|
dict:get(key) | [dict objectForKey:key] |
dict:set(key, value) | [dict setObject:value forKey:key] |
dict:haskey(key) | [dict objectForKey:key] != nil |
dict:remove(key) | [dict removeObjectForKey:key] |
dict:count() | [dict count] |
Lua Syntax | Mapped Call |
---|---|
arr:get(index) | [arr objectAtIndex:index-1] |
arr:insert(index, value) | [arr insertObject:value atIndex:index-1] |
arr:add(value) | [arr addObject:value] |
arr:remove(index) | [arr removeObjectAtIndex:index-1] |
arr:count() | [arr count] |
To be the same convention as Lua, the index
used Lua script is 1-based, and it automatically minus 1 in Objective-C to be 0-based.
Loc also provides totable()
method for NSDictioanry
and NSArray
, it converts instance of NSDictioanry
or NSArray
to Lua table. However, it only convert one depth level, it does not recursively convert keys and values.
With totable()
, we could use the result in pairs(t)
or ipairs(t)
to interate content in for
loop.
for k,v in pairs(dict:totable()) do
-- iteration body
end
for i,v in ipairs(arr:totable()) do
-- iteration body
end
Loc provides some auxiliary methods to use in Lua script, all methods are in global loc
table. The list below shows the methods we can use Lua:
loc.toclass(str)
loc.todictionary(table)
loc.toarray(table)
We don't use loc.todictionary()
very often, as Loc converts table to NSDictionary
as default. But if some methods accept NSArray as arguemnts, we need to manually convert table to NSArray
with loc.toarray()
, then pass to method.
Loc allows us to call Class method as well, but it limits to method with no arguments. So we could even construct a new object in Lua:
local clazz = loc.toclass('SomeClassName');
local obj = clazz:alloc():init();
It's totally work, but not recommended, because we really do not want Lua to handle Objective-C memory management.
The common usage is call some method to get singleton of a Class:
local obj = clazz:instance();
Loc is not able to call Class Methods with any argument yet.
Lua is scripting language like PHP, Javascript. It can access value of table by variable, not just type in code. Loc support it as well, but not very well.
We can use brackts to access property on Objective-C object, and assign value to it:
local prop = 'name';
obj[prop] = 'newName';
But if we want to get value, we need to call as method, and pass object as first argument:
local name = obj[prop](obj);
local funcName = 'addAWithB';
obj[funcName](obj, 21, 7);
This is just how Lua dot(.) syntax work.
Supported by Ider