The Tiny Lua Cocoa Bridge
Pull request Compare This branch is 8 commits ahead, 9 commits behind fjolnir:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.

TLC - The Tiny Lua Cocoa Bridge

TLC is a very compact and minimal Objective-C bridge for LuaJIT. Written by Fjõlnir Ásgeirsson

Simple Example

local objc = require("objc")
pool = objc.NSAutoreleasePool:new()
objc.NSSpeechSynthesizer:new():startSpeakingString(objc.NSStr("Hello From Lua!"))
os.execute("sleep "..2)


TLC supports the following:

  • Loading frameworks
  • Accessing Objective-C objects
  • Creating Objective-C classes
  • Calling methods on said objects
  • Creating blocks from Lua functions
  • Converting the basic lua types to objects (Explicitly)
  • Loading BridgeSupport files

TLC Does not yet support the following:

  • Calling methods that take a variable number of arguments
  • Defining variadic blocks, methods or callbacks, or ones that take pass-by-value(non-pointer) structs or unions. (A limitation of LuaJIT FFI)

Loading TLC

local objc = require("objc")

Loading frameworks


-- You can also use BridgeSupport
-- It is slower, but you get access to all C types, functions & constants automatically
local bs = require("objc.BridgeSupport")
-- You can then access constants using bs = bs.CGPointZero

Accessing Objective-C objects

local NSString = objc.NSString

Calling Methods

local myStr = NSString:stringWithUTF8String("I am an NSString.")

-- Calling selectors with multiple arguments requires replacing the colons with underscores
-- Except the ones at the end, they are optional.
-- Example selector:with:multiple:parameters: => selector_with_multiple_parameters()
--         selectorWithAnonymousParams:::: => selectorWithAnonymousParams()
local anObject = MyObject:selector_with_multiple_parameters(arg1, arg2, arg3, arg4)

Converting the Basic Lua Types to Objects

-- If you know the type of the variable you want to convert you should use these functions
local string     = NSStr("foobar")
local number     = NSNum(123)
local array      = NSArr({"a","b","c"})
local dictionary = NSDic({ a=1, b=2, c=3 })
-- If not,
-- The Obj() function takes an arbitrary value and determines the correct class to convert it to
local object = Obj(anyVariable)

Subclassing & Extending of Classes

-- This creates a class and registers it with the runtime (it is also accessible with objc.MyClass after creation)
-- The dictionary specifies an instance variable of type int(type encoding: i)
-- To learn about type encodings read
local MyClass = objc.createClass(objc.NSObject, "MyClass", { ivar="i" })

-- Creates an init method returning an object(@) and taking as arguments an object(@) and a selector(:)
-- All methods must take self and selector as their first two arguments
objc.addMethod(MyClass, objc.SEL("init"), function(self, sel)
	print("Creating an instance of", self:class())
	objc.setIvar(self, "anIvar", 123)
	return objc.callSuper(self, sel)
end, "@@:")

-- Add a getter for 'ivar'
objc.addMethod(MyClass, objc.SEL("ivar"), function(self, sel)
	return objc.getIvar(self, "ivar")
end, "i@:")
-- Add a setter for 'ivar'
objc.addMethod(MyClass, objc.SEL("setIvar:"), function(self, sel, anIvar)
	objc.setIvar(self, "ivar", anIvar)
end, "v@:i")

-- 'instance' is an object pointer usable on the lua side as well as the objective-c side
local instance = MyClass:alloc():init()

Creating Blocks from Lua Functions

-- To create a block you call createBlock with it's type encoding (Default being void return and no argument)
-- A block returning an integer and taking one object and one double as arguments
local block = objc.createBlock(function(object, double)
	print("I was passed these arguments: ", object, double)
	return 123
end, "i@d")

(Dirty Secret Trick)

-- If you don't want to type 'objc.' before using a class you can set the global namespace to use it as a fallback
setmetatable(_G, {__index=objc})
-- And then you can simply write the class names without the 'objc.' prefix
obj = CoolClass:doThings()