» 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.

    <div class='code'><pre class="dawn">NS.String <span class="Comment"><span class="Comment">--</span> Returns the NSString class</span>&#x000A;UI.View <span class="Comment"><span class="Comment">--</span> Returns the UIView class</span>&#x000A;&#x000A;UI.TableView <span class="Comment"><span class="Comment">--</span> This is just syntactic sugar for the line below.</span>&#x000A;wax.class[&quot;UITableView&quot;] <span class="Comment"><span class="Comment">--</span> This is the raw Wax call</span>&#x000A;</pre></div>
    
    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.

    <div class='code'><pre class="dawn">waxClass{&quot;MyClass&quot;, NS.Object}&#x000A;&#x000A;<span class="Comment"><span class="Comment">--</span> If you need to add protocols, add them like this</span>&#x000A;waxClass{&quot;MyClass&quot;, NS.Object, protocols <span class="Keyword">=</span> {&quot;UITableViewDelegate&quot;, &quot;UITableViewDataSource&quot;}}&#x000A;&#x000A;<span class="Comment"><span class="Comment">--</span> REMEMBER! Protocols need to be added as strings since they are not classes.</span>&#x000A;</pre></div>
    
  • 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.

    <div class='code'><pre class="dawn">waxClass{&quot;MyClass&quot;, NS.Object}&#x000A;<span class="Comment"><span class="Comment">--</span> is equivalent to...</span>&#x000A;waxClass({&quot;MyClass&quot;, NS.Object})&#x000A;<span class="Comment"><span class="Comment">--</span> ...omitting the parenthesis is much more pretty, so that's how we roll.</span>&#x000A;</pre></div>
    
  • 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.

    <div class='code'><pre class="dawn"><span class="Comment"><span class="Comment">--</span> A method called with a colon : in Lua ...</span>&#x000A;UI.Application:sharedApplication()&#x000A;&#x000A;<span class="Comment"><span class="Comment">--</span> ... is equivalent to this</span>&#x000A;UI.Application.sharedApplication(UI.Application)&#x000A;&#x000A;<span class="Comment"><span class="Comment">--</span> So we just use the colon : to keep this DRY and readable!</span>&#x000A;</pre></div>
    
  • 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.

    <div class='code'><pre class="dawn"><span class="Comment"><span class="Comment">--</span> A method called with a colon : in Lua ...</span>&#x000A;<span class="Keyword">local</span> view <span class="Keyword">=</span> UI.View:init()&#x000A;&#x000A;view.someRandomVariable <span class="Keyword">=</span> &quot;YEAH!&quot;&#x000A;<span class="Comment"><span class="Comment">--</span> You can assign anything to an instance and it will stick around</span>&#x000A;</pre></div>
    
  • If an obj-c method takes multiple arguments, the method call uses underscores _ instead of colons like in obj-c.

    In obj-c...
    <div class='code'><pre class="dawn">[UIAlertView initWithTitle:@&quot;title&quot; message:@&quot;message&quot; delegate:nil];&#x000A;</pre></div>
    
    With Wax...
    <div class='code'><pre class="dawn">UI.AlertView:initWithTitle_message_delegate(&quot;title&quot;, &quot;message&quot;, <span class="Constant">nil</span>)&#x000A;</pre></div>
    
  • 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.

    <div class='code'><pre class="dawn"><span class="Keyword">local</span> fileManager <span class="Keyword">=</span> NS.FileManager:defaultManager()&#x000A;<span class="Keyword">local</span> contents <span class="Keyword">=</span> fileManager:directoryContentsAtPath(&quot;.&quot;)&#x000A;<span class="Comment"><span class="Comment">--</span> directoryContentsAtPath returns an NSArray, but Wax turns this into a Lua</span>&#x000A;<span class="Comment"><span class="Comment">--</span> table, which is totally cooler.</span>&#x000A;&#x000A;<span class="SupportFunction">print</span>(contents[<span class="Constant">1</span>]) <span class="Comment"><span class="Comment">--</span>&gt; &quot;info.plist&quot;</span>&#x000A;&#x000A;<span class="Comment"><span class="Comment">--</span> NSDictionaries become Lua tables</span>&#x000A;<span class="Comment"><span class="Comment">--</span> NSArrays and NSSets become Lua tables</span>&#x000A;<span class="Comment"><span class="Comment">--</span> NSStrings become Lua strings</span>&#x000A;<span class="Comment"><span class="Comment">--</span> NSNumbers become Lua numbers</span>&#x000A;</pre></div>
    
  • Sometimes you don't want an obj-c object to be coerced, for that use the toobjc method.

    <div class='code'><pre class="dawn"><span class="Comment"><span class="Comment">--</span> if you are trying to call an NSString method, this will fail ...</span>&#x000A;<span class="Keyword">local</span> string <span class="Keyword">=</span> &quot;a string&quot;&#x000A;string:capitalizedString()&#x000A;<span class="Comment"><span class="Comment">--</span> ... because string is coerced into a Lua string</span>&#x000A;&#x000A;<span class="Comment"><span class="Comment">--</span> This will force string to behave like an NSString</span>&#x000A;toobjc(string):capitalizedString()&#x000A;</pre></div>
    
  • 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.

    <div class='code'><pre class="dawn">wax.struct.create(&quot;CGRect&quot;, &quot;ffff&quot;, &quot;x&quot;, &quot;y&quot;, &quot;width&quot;, &quot;height&quot;)&#x000A;&#x000A;<span class="Comment"><span class="Comment">--</span> The creates a global function called CGRect that takes 4 float arguments,</span>&#x000A;<span class="Comment"><span class="Comment">--</span> the second argument &quot;ffff&quot; is what defines the argument types.</span>&#x000A;&#x000A;<span class="Keyword">local</span> rect <span class="Keyword">=</span> CGRect(<span class="Constant">1</span>, <span class="Constant">2</span>, <span class="Constant">3</span>, <span class="Constant">4</span>)&#x000A;<span class="SupportFunction">print</span>(rect.x) <span class="Comment"><span class="Comment">--</span>&gt; 1</span>&#x000A;rect.x <span class="Keyword">=</span> <span class="Constant">200</span>&#x000A;<span class="SupportFunction">print</span>(rect.x) <span class="Comment"><span class="Comment">--</span>&gt; 200</span>&#x000A;</pre></div>
    

User Comments

Recent Posts

    Archive

    • Wax talks to Twitter - October 20, 2009
    • How does iPhone Wax work? - October 19, 2009
    • Setting up iPhone Wax - October 18, 2009
    • 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.