Warren Burton's accepted answer, utilising a strong reference to a @NSApplicationMain-annotated AppDelegate instance no longer works. I've confirmed it myself on OS X High Sierra, and Alex Sieroshtan commented that it didn't work back in OS X Yosemite, either. The failure point, as Tyler Durden noted, was this message:
Assertion failure in -[X.XApplication init], /Library/Caches/com.apple.xbs/Sources/AppKit/AppKit-1504.82.104/AppKit.subproj/NSApplication.m:1778
2017-04-08 13:25:35.761585+0100 X
[9073:1059806][General] An uncaught exception was raised 2017-04-08 13:25:35.761601+0100 X
[9073:1059806][General] Creating more than one Application
I struggled with this myself for a good while, but came up with two up-to-date solutions by no small amount of experimentation.
Option 1: Continue to use @NSApplicationMain via a workaround
I found that you can alter the code of the accepted answer to work around the bug. The way to do this is by not calling the super.init() method in your class named AppDelegate.
What?
Really. I think there is a too-eager assertion counting number of inits done by AppDelegate (or some logic along these lines), and thus the call to super.init() gets counted as well as the completion of the override init() block. You have two options for workarounds here:
Don't call super.init(): This is actually possible and completely healthy for NSObject, at least in macOS. You lose the ability to reference self in the override init() block, however.
Don't override init() at all: Consider doing your init process during a lifecycle method like applicationWillFinishLaunching(:).
I don't recommend either of these, of course.
Option 2: Give up on the @NSApplicationMain method altogether
@NSApplicationMain is just a macro which we can approximate ourselves. By some luck, I came across James H Fisher's blog post explaining how. I'll quote what matters in a moment.
If you have written @NSApplicationMain anywhere, please delete it before proceeding with these instructions.
No need to alter your Info.plist file
The key:value pair for NSPrincipalClass should keep its default value of:
<key>NSPrincipalClass</key>
<string>NSApplication</string>
Use main.swift instead of subclassing NSApplication
The file MUST be called main.swift; it's a special exception to Swift's "Expressions are not allowed at the top level" rule.
import AppKit
let app = NSApplication.shared
let delegate = AppDelegate()
app.delegate = delegate
_ = NSApplicationMain(CommandLine.argc, CommandLine.unsafeArgv)
The logic
James H Fisher explains, referencing the NSApplication documentation:
[Docs]
Every app must have exactly one instance of NSApplication (or a subclass of NSApplication). Your program’s main() function should create this instance by invoking the shared() class method.
[James]
First, main.swift runs NSApplication.shared, and assigns this NSApplication object to myApp. Notice the documentation refers to a main() function, even though in Swift there is none! The equivalent is the main.swift file.
Next, main.swift instantiates your AppDelegate class, and assigns it as the .delegate of myApp. You can now see why the default project chooses to call the class AppDelegate: it is set as the .delegate on an NSApplication.
Finally, main.swift calls the function NSApplicationMain(...)... The function NSApplicationMain(...) is the entry point for Cocoa applications. NSApplicationMain(...) never returns; instead, it sets up the UI event loop, and eventually exits using the C exit(...) function.
Additionally this StackOverflow post goes into some detail about why using sharedApplication remedies the "Creating more than one Application" bug.
... That's all you need! Hope this serves to help somebody else.