Is it possible to create a headless macOS app using @main on an app delegate class without code to explicitly instantiate it? No storyboard, no SwiftUI, just:
@main
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ notification: Notification) {
// Never gets called.
}
I understand this to be the case, but I created my Xcode project from a SwiftUI template. I've removed the SwfitUI app definition, and there are no Info.plist keys referring to anything. I tried adding NSPrincipleClass = NSApplication, but this key doesn't appear in the built Info.plist, and it also seems to be a build setting in the target.
I also tried @NSApplicationMain but it did’t seem to change anything.
I'm trying to run an AppKit app, and main should be synthesized. I'm able to make it work by explicitly providing a main that instantiates my app delegate and calls NSApplicationMain, but my understanding is Xcode should do that for me.
Compiler does call NSApplicationMain for you.
If you add symbolic breakpoint for NSApplicationMain, you can see (stepping through assembler) that NSApplicationMain does indeed run and initializes NSApplication instance. It's just that if there is no storyboard to load, it tries to load nib file, which fails because there is none in your case. But since nib file was never named in the first place it decides to just skip to [NSApplication run].
This results in NSApplication running, but your code never gets to run, because delegate object is never initialized.
It seems your options are either to manually write main or keep storyboard/xib in project, just remove any windows from them (be sure you do not remove AppDelegate association). Second option will result in application running without window, but with menu.
There’s no such thing as a headless AppKit app—NSApplication needs to connect to the WindowServer in order to consume events.
A windowless AppKit app is simple to create—just delete the window from your MainMenu.xib and never create another one. As @ibex pointed out, if your app delegate instance lives in MainMenu.nib, this is the only way it will be created.
Changing your app’s activation policy dynamically can result in all sorts of weirdness. Most apps don’t need to do that, and thus are much better off declaring it statically via one of those Info.plist properties.
If only the docs would include comments like this. There is so much useful knowledge in your Comments, that is sadly so well hidden in the vastness of the internet