Swift: Today’s Wow moment. Adding menus to playgrounds

I finally figured out how to get a nib/xib loaded into a playground and use it to power an app menu. It’s ridiculous how long this took and how simple the solution turned out to be.

Each playground, regardless of whether you’re building iOS or OS X code, runs as a tiny independent app on your computer. You can find that executable, and the app it is running in by peeking at NSBundle.mainBundle().executablePath.

Playground apps are tiny.  OS X versions consist of a minimal bundle with a stripped-down Info.plist, a Resources folder, and a MacOS executable.

You can throw a xib file into your Resources, but the playground cannot read it or run it because it’s not in compiled form. Today, I (finallly!) thought of using ibtool to pre-compile my MainMenu.xib file into nib and then load that. When you install Xcode’s command line tools, ibtool gets added to /usr/bin. So all you need to do to compile your nib is issue the following command:

ibtool --compile MainMenu.nib MainMenu.xib

Throw that resulting nib into your playground’s resources folder and you’re ready to load it up.

The trickiest bit was trying to get all the unsafe autoreleasing mutable pointer stuff working. Swift is like a perfect haiku. It all looks simple and obvious when you’ve finished writing it but getting it debugged is a pain. The answer, by the way is this, which hopefully people will be able to google up without having to go through an hour or two of tweakage:

var array = NSArray()
var outputValue = AutoreleasingUnsafeMutablePointer<NSArray?>(&array)
NSBundle.mainBundle().loadNibNamed("MainMenu", owner: nil, topLevelObjects: outputValue)

A few further points:

I built a simple compile command line shell script so I don’t have to remember the order of the files or the arguments for ibtool. You can see it in the video in the Resources folder.

Add your xib source into your Resources as well as your compiled nib. You can then edit the xib using Xcode editors directly from the playground workspace. You still have to compile outside it. I keep a terminal window open to simplify the process.

Every now and then Xcode automatically moves things around, so use a full path in the terminal. Then use the terminal’s history to re-issue the same command as needed:

cd /Users/ericasadun/Desktop/Playgrounds/X\ -\ Playgrounds/OSX\ Menu.playground/Resources ; ./compile

Don’t compile when your nib is in use.  Comment out the XCP indefinite execution line and the loadNibNamed line, and then compile in place from the command line.

You can’t much in the way of binding in your xib but you can design stuff there and then add the targets and behavior in the playground.

Comments are closed.