probablycorey edited this page Feb 10, 2011 · 5 revisions

Here is a quick tour of the Wax framework. By the end you should have a better understanding of how Wax interacts with Objective-C.

  • Wax is a Lua bridge to Objective-C. This means you can write Lua that talks to Objective-C and you can write Objective-C that talks with Lua!

  • Accessing a Cocoa class in Lua (via Wax) looks just like Objective-C

    NSString -- Returns the NSString class
    UIView -- Returns the UIView class

    UITableView -- This is just syntactic sugar for the line below.
    wax.class["UITableView"] -- This is the raw Wax call, you probably didn't need to know this
  • When you create an instance of an Objective-C object DON'T call alloc, wax handles this for you.
    -- No need to call alloc, retain or release! ZOMG!
    local view = UIView.initWithFrame(CGRect(0, 0, 100, 100))
  • To create an Objective-C class from Lua, call the function waxClass{CLASS\_NAME, PARENT_CLASS}. All subsequent functions (within the same file) you add to that Lua file will be automatically added to your new class as instance methods.
    waxClass{"MyClass", NSObject}

    -- Add protocols like this
    waxClass{"MyClass", NSObject, protocols = {"UITableViewDelegate", "UITableViewDataSource"}}

    -- REMEMBER! Protocols need to be added as strings (This is because they are not classes)
  • Calling a Lua function with brackets {} instead of parenthesis () (like in the above call to waxClass) is just syntactic sugar for calling a function with a single table as the argument.
    waxClass{"MyClass", NSObject}
    -- is equivalent to...
    waxClass({"MyClass", NSObject})
    -- ...omitting the parenthesis is much more pretty, so that's how we roll.
  • For waxClass functions, the first argument must be self. This is how Wax mimics Objective-C's object orientated model.
    waxClass{"MyClass", NSObject}

    -- Notice the first argument is self... this will hold the instance of `MyClass` 
    function storeWords(self, words)
      self.words = words

      -- Wax creates a `super` variable on the self object. 
      -- Use that to call a method on the object's super class.
  • Use a colon : instead of a dot . when you call any Objective-C method. This passes the calling object in as the first argument to the method.
    -- A method called with a colon : in Lua ...

    -- ... is equivalent to this

    -- So we just use the colon : to keep this DRY and readable!
  • If an Objective-C method takes multiple arguments, the method call uses underscores _ instead of colons like Objective-C does.

    In Objective-C...

    [UIAlertView initWithTitle:@"title" message:@"message" delegate:nil];

With Wax...

    UIAlertView:initWithTitle_message_delegate("title", "message", nil)
  • Wax DOESN'T use Objective-C properties. Wax forces Lua and Objective-C to only communicate with methods
    someView.frame -- This WON'T work. 

    -- You want to use the getter/setter methods instead
  • You can dynamically create member variables for any Objective-C object using the dot . operator. Unlike the colon : operator (used to call methods on an Objective-C class/instance) the dot . operator dynamically creates member variables on the Lua side of the object (The Objective-C side of the object has no knowledge of these variables). The member variables are available throughout the lifetime of the object.
    -- A method called with a colon : in Lua ...
    local view = UIView:init()

    view.someRandomVariable = "YEAH!"
    -- You can assign anything to an instance and it will stick around 
  • Wax will try and coerce Objective-C objects into Lua primatives. It also does the reverse, if an Objective-C methods takes an NSString argument, you can just pass it a Lua string.
    local fileManager = NSFileManager:defaultManager()
    local contents = fileManager:directoryContentsAtPath(".")
    -- directoryContentsAtPath returns an NSArray, but Wax turns this into a Lua
    -- table, which is totally cooler.

    print(contents[1]) --> "info.plist"

    -- NSDictionaries become Lua tables
    -- NSArrays become Lua tables
    -- NSStrings become Lua strings
    -- NSNumbers become Lua numbers
  • Sometimes you don't want an Objective-C object to be coerced, for that use the toobjc method.
    -- if you are trying to call an NSString method, this will fail ...
    local string = "a string"
    -- ... because string is coerced into a Lua string

    -- Instead use toobjc, it will force string to be a NSString
  • Enums, like UITableViewStylePlain, are hardcoded. For now the most commonly used ones are declared in APP_ROOT/wax/stdlib/enums.lua. In the future I hope to get BridgeSupport working for the iPhone so all enums & structs can be created automatically.

  • To pass a selector, just use a string. For example in Objective-C selectors are written as @selector(this:is:a:method). In Wax they are written as this:is:a:method.

  • Structs are also tricky, the most common ones are decalred in APP_ROOT/wax/wax-scripts/structs.lua. It is easy to add structs by following the pattern found in the structs.lua file.

    wax.struct.create("CGRect", "ffff", "x", "y", "width", "height")

    -- The creates a global function called CGRect that takes 4 float arguments,
    -- the second argument "ffff" is what defines the argument types.

    local rect = CGRect(1, 2, 3, 4)
    print(rect.x) --> 1
    rect.x = 200
    print(rect.x) --> 200