» How does iPhone Wax work?

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's Lua Syntax

  • In Wax, Cocoa classes are namespaced to keep the global scope clean. To access a class you put a dot . between the framework prefix and the class name.

    NS.String -- Returns the NSString class
    UI.View -- Returns the UIView class
    
    UI.TableView -- This is just syntactic sugar for the line below.
    wax.class["UITableView"] -- This is the raw Wax call
    

    To see how this works check out the cocoaNamespace calls in APP_ROOT/wax/wax-scripts/init.lua

  • To write your own obj-c object, create a new file with a call to waxClass(CLASS_NAME, PARENT_CLASS) at the top.

    waxClass{"MyClass", NS.Object}
    
    -- If you need to add protocols, add them like this
    waxClass{"MyClass", NS.Object, protocols = {"UITableViewDelegate", "UITableViewDataSource"}}
    
    -- REMEMBER! Protocols need to be added as strings since 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", NS.Object}
    -- is equivalent to...
    waxClass({"MyClass", NS.Object})
    -- ...omitting the parenthesis is much more pretty, so that's how we roll.
    

  • The waxClass function creates an obj-c class via the obj-c runtime. All subsequent functions (within the same file) you add to that Lua file will be automatically added to your new class as instance methods.

  • For waxClass functions, the first argument must be self. This is how Wax mimics obj-c's object orientated model.

    waxClass{"MyClass", NS.Object}
    
    -- Notice the first argument is self... this will hold an 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.
      self.super:words(self)
    end
    

  • Use a colon : instead of a dot . when you call any obj-c method. This secretly passes the calling object in as the first argument to the method.

    -- A method called with a colon : in Lua ...
    UI.Application:sharedApplication()
    
    -- ... is equivalent to this
    UI.Application.sharedApplication(UI.Application)
    
    -- So we just use the colon : to keep this DRY and readable!
    

  • You can dynamically create member variables for any obj-c object using the dot . operator. Unlike the colon : operator (used to call methods on an obj-c class/instance) the dot . operator dynamically creates member variables on the Lua side of the object (The obj-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 = UI.View:init()
    
    view.someRandomVariable = "YEAH!"
    -- You can assign anything to an instance and it will stick around
    

  • If an obj-c method takes multiple arguments, the method call uses underscores _ instead of colons like in obj-c.

    In obj-c...

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

    With Wax...

    UI.AlertView:initWithTitle_message_delegate("title", "message", nil)
    

  • Wax will try and coerce obj-c objects into Lua. It also does the reverse, if an obj-c methods takes an NSString argument, you can just pass it a lua string.

    local fileManager = NS.FileManager: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 and NSSets become Lua tables
    -- NSStrings become Lua strings
    -- NSNumbers become Lua numbers
    

  • Sometimes you don't want an obj-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"
    string:capitalizedString()
    -- ... because string is coerced into a Lua string
    
    -- This will force string to behave like an NSString
    toobjc(string):capitalizedString()
    

  • Enums, like UITableViewStylePlain, are a bit tricky. For now the most commonly used ones are declared in APP_ROOT/wax/wax-scripts/enums.lua. In the future I hope to get BridgeSupport working for the iPhone so all enums & structs can be created automatically.

  • 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
    

User Comments

Recent Posts

  • Wax talks to Twitter - October 20, 2009
  • How does iPhone Wax work? - October 19, 2009
  • Setting up iPhone Wax - October 18, 2009
  • Archive

    • Ruby (tinyrb) on iPhone - May 03, 2009
    • Building PCRE static lib for the iPhone - May 02, 2009
    • Amazon EC2 + Chef = Mmmmm - March 29, 2009
    • Objective-c key paths - February 13, 2009
    • POW! - December 26, 2008
    • Abusing Ruby's question mark methods. - November 28, 2008
    • Git hooks make me giddy - November 07, 2008
    • Ruby Equality! equal? eql? == and === - October 26, 2008
    • Ruby, Rails and Google Sitemaps - October 20, 2008
    • Projects

      • Wax Obj-C to Lua bridge for iPhone.
      • Pow a Ruby library for making file & directory manipulation easy.
      • MiniMagick a tiny RMagick replacement.