3

Many people appear to have a problem where their AppDelegate's applicationShouldTerminate is never called. I have the opposite problem!

Often (at a guess 20% of the time) when I come back to my Mac in the morning, I discover that something caused my app's applicationShouldTerminate to fire. My app then ran its cleanup code, after which applicationWillTerminate fired. However the app never shut down — it's still marked as running in my dock, and when I click on it there, applicationDidFinishLaunching fires and it starts up. Because it was already running, the dock icon does not bounce.

The logs indicate this seems to only happen when I wrap up for the day and my Mac goes to sleep, possibly only after having been plugged back in after running off its battery.

At first I thought it might be because my Mac was trying to shutdown apps to install a system update but this happens even when there are no updates available. And no other apps on my system have the issue.

The same happens with my app on a friend's Mac.

I do have a "tricky" applicationShouldTerminate to get around run loop issues (nb. I'm using Promises):

var shuttingDown: Bool = false

func applicationShouldTerminate(_ sender: NSApplication) -> NSApplication.TerminateReply {
    log.debug("applicationShouldTerminate")

    if shuttingDown { return .terminateNow }
    shuttingDown = true

    StuffController.shared.terminateRunningStuff()
        .timeout(20) // If it hasn't shutdown within 20 seconds, force it.
        .always {
            // Tell the app it should now actually terminate.
            NSApplication.shared.terminate(self)
        }

    return .terminateCancel
}

Can anyone suggest a reason my applicationShouldTerminate is firing without the user asking it to quit?

jeff-h
  • 2,184
  • 1
  • 22
  • 33

1 Answers1

1

Turns out this is a feature not a bug (lol). In Mac OS X Lion (10.7) Apple introduced a feature called "Automatic Termination" where apps would automatically quit after a while of inactivity.

Note that this is intended to be invisible to the end-user; the app appears to be running in the dock, and should restore itself when needed, as if nothing ever happened.

It can be enabled or disabled via the "Application can be killed to reclaim memory or other extraordinary circumstances" configuration in Xcode (the NSSupportsAutomaticTermination key in an app's Info.plist).

jeff-h
  • 2,184
  • 1
  • 22
  • 33