…sitting in a tree, K-I-S-S-I-N-G…
So, all of the cool kids have been talking about Laurent Sansonetti’s next project: RubyMotion, a port of MacRuby targeted at iOS. On the whole I’m pretty impressed with what you can already do with it. One of the issues that people having been mentioning though, is that you lose the ability to use Interface Builder with it, but this isn’t actually true!
Here I’m going to show you how to work with Interface Builder, I’ll base the project off the one used in the Pragmatic Studio screencast (the icon and background images come from there as well, by the way).
Update: the images don’t dome from there any more! The images used in the screencast are from iStockPhoto, so I’ve replaced the background image with a different one. Needless to say this doesn;t affect any of the code.
All of the code for this project can be found on GitHub.
Setting up a Project
Start off as normal:
motion create MagicBallDemo. In the project folder create a new subfolder called interfaces, this is where all of the
.xib files will be saved.
Next create a model class called
MagicBall and a view controller called
MagicViewController which extends
UIViewController, also create a file to store some small helper methods called
helpers.rb. Don’t worry about the contents of these files for now, I’ll come back to them, but you should have the following:
1 2 3 4 5 6
The next thing to do is create the UI using interface builder.
Creating the User Interface
Open Xcode and hit ⌘-N to create a new file, select the Empty template and save the file into the folder you just created. Now add a
View Controller from the object library and set the custom class to
MagicViewController; you can’t edit this field directly but you can paste into it, so select the class name from
The next step is to add the view to it’s controller, normally this would just mean dragging a
UIImageView on top of the controller but that won’t work here. There is a problem with interface builder in that you can’t add subviews to
UIImageViews, which is a pain in the ass. A simple workaround is described in this Stack Overflow question, and that’s what we’ll do here. So, add a
UIView to the view controller and set it’s custom class to be
UIImageView (which should be available in the pick-list). You can’t set the image here, that will need to be done in code.
Finally add the label and configure it as desired. Save your changes and close XCode.
You can compile this into a
ibtool, this script will compile all of the interfaces in your project (just one in this case):
1 2 3 4 5
Update: as of RubyMotion 1.3 this happens automatically, no need to compile your nibs by hand and more!
Connecting up the Code
The first thing we need to do is make sure our app delegate loads the interface from the nib that we’ve created, and we set our
@window ivar from the loaded nib.
1 2 3 4 5 6 7
The nib loading process will create an instance of our view controllor for us, but we need to wire up a few connections add add some behaviour, here’s a simplified version of the code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
I know that there is only 1 subview so it’s easy to grab a reference to the label and store it in an ivar, a more realisic example could
select the label based on a tag.
As mentioned above, I need to explicitly set the image and this happens here as well.
Finally, set up the gesture recognizer. This is one place that Ruby shines, it’s trivial for us to add helper methods like this, have a look in
app/helpers.rb for the code that enabled this.
It’s a good idea to add
resources/*.nib to the
.gitignore file as compiled resources don;t need to be committed to Git. I also add
doc/app then I can use rocco to generate some documentation.
Take a look at the full project on GitHub and let me know what you think!
Update: clarified the wording around adding the