How is MainMenu.xib found in Cocoa?

In Xcode, go to File > New > Project, select “Cocoa application”. Run it. You get an empty window, and a menu bar for it along the top. This menu bar contains a whole lot of functionality. Where did all this functionality come from?!

In short: the default project gives you a MainMenu.xib and an AppDelegate.swift. The AppDelegate class has the @NSApplicationMain annotation, which causes your program to call the NSApplicationMain function, which in turn has some routines which load the MainMenu.xib file, which contains several hundred lines which describe the window, menu, and other things.

But how does NSApplicationMain find your MainMenu.xib file, and what does it do with it then? The docs for NSApplicationMain are a bit vague:

Creates the application, loads the main nib file from the application’s main bundle, and runs the application.

First, how does NSApplicationMain find your MainMenu.xib file? The search procedure begins with key NSMainNibFile in Info.plist. If this key exists, it’s used to load the file. We can emulate this behavior in our main.swift:

import Cocoa
let myApp: NSApplication = NSApplication.shared()
let mainBundle: Bundle = Bundle.main
let mainNibFileBaseName: String = mainBundle.infoDictionary!["NSMainNibFile"] as! String
mainBundle.loadNibNamed(mainNibFileBaseName, owner: myApp, topLevelObjects: nil)
_ = NSApplicationMain(CommandLine.argc, CommandLine.unsafeArgv)

However, if the NSMainNibFile key is not present, NSApplicationMain falls back the first nib/xib file which it happens to find in the main bundle. We can’t emulate this behavior easily. If you have nib/xib files in your bundle which you don’t want to use as the main nib, you should hide them away so that NSApplicationMain doesn’t find them.

Tagged .
👋 I'm Jim, a full-stack product engineer. Want to build an amazing product and a profitable business? Read more about me or Get in touch!

More by Jim

This page copyright James Fisher 2017. Content is not associated with my employer. Found an error? Edit this page.