Learn more about Russian war crimes in Ukraine.

How to make a Cocoa application without a .xib file

In XCode, go to File > New > Project... and select “Cocoa Application”. Call it “Foo”, then uncheck all of the “Use Storyboards”, “Use Core Data”, and other nonsense. You get a project which, when you run it, displays a window with the title “Foo”. How does that window get there?

Turns out, even though you unchecked “Use Nonsense”, you still get a nonsense file: that MainMenu.xib. What is it, and how do we get rid of it? Cocoa applications begin with a call to NSApplicationMain. In C and Objective-C, you call NSApplicationMain from your main function. The call to NSApplicationMain never returns; instead, it sets up the UI event loop which runs until the program exits with the exit function.

It is the NSApplicationMain call which “loads the main nib file from the application’s main bundle”. (For “nib”, read “xib”: the “nib” format is an older syntax which was replaced with the XML-based “xib” format.)

It is unclear how NSApplicationMain finds the “main xib file” which it loads. One way is via the NSMainNibFile in your Info.plist file. However, if you remove this key in the plist file, Cocoa still finds your xib file. It will even find your xib file if you rename it Foo.xib. It is as if Cocoa falls back to a general search for files ending in .xib.

If, like me, you’re using Swift, it will also be unclear how NSApplicationMain is called. You will have seen the similarly named @NSApplicationMain annotation on your AppDelegate class. You can see it in the default AppDelegate.swift, which looks like:

import Cocoa
class AppDelegate: NSObject, NSApplicationDelegate {
    @IBOutlet weak var window: NSWindow!

The @NSApplicationMain annotation can be seen a bit like a macro. Roughly, it will create a main.swift file with these contents:

import AppKit
let app: NSApplication = NSApplication.shared()
let appDelegate = AppDelegate()  // Instantiates the class the @NSApplicationMain was attached to
app.delegate = appDelegate
_ = NSApplicationMain(CommandLine.argc, CommandLine.unsafeArgv)

The main.swift file is special: it can contain top-level statements. It’s a bit like the body of the main function in C. Replace @NSApplicationMain with this main.swift, and then you can remove your MainMenu.xib file.

What can computers do? What are the limits of mathematics? And just how busy can a busy beaver be? This year, I’m writing Busy Beavers, a unique interactive book on computability theory. You and I will take a practical and modern approach to answering these questions — or at least learning why some questions are unanswerable!

It’s only $19, and you can get 50% off if you find the discount code ... Not quite. Hackers use the console!

After months of secret toil, I and Andrew Carr released Everyday Data Science, a unique interactive online course! You’ll make the perfect glass of lemonade using Thompson sampling. You’ll lose weight with differential equations. And you might just qualify for the Olympics with a bit of statistics!

It’s $29, but you can get 50% off if you find the discount code ... Not quite. Hackers use the console!

More by Jim

Tagged . All content copyright James Fisher 2017. This post is not associated with my employer. Found an error? Edit this page.