Disable App Nap in macOS

September 15, 2016

Disable App Nap in macOS

I am currently writing an app for OS X that is going to controlling my new Philips Hue lights. At one point I have noticed that the speed of the process my app does drops significantly after some period of time in case a window of the app in minimized or not visible on the screen.
I knew what might be the issue - App Nap feature of macOS. An urge to disable app nap was quite natural.
Here is how to turn it off as well as some hints.

<!--more-->

ProcessInfo

In order to prevent app nap you have to inform the system about you performing some work which should not be interrupted by the OS i.e. putting your application into a 'nap'. To do that you use ProcessInfo class.
I strongly encourage you to go ahead and read the documentation on what this class can do for you as I am going to concentrate only on the problem you might encounter - "I called the proper methods, why does my app still goes into a nap mode?!". This type of question.

Prevent App Nap

First of all you have to make a property in your class that is going to hold an instance of NSObjectProtocol - an object token representing the activity. Then you call beginActivity(options:reason:) method to disable app nap. After you are done and you want to save some energy - you end your activity by calling endActivity() method to notify the system.

var activityToken: NSObjectProtocol?

func yourMethod() {
    let options = [.AutomaticTerminationDisabled, .UserInitiated, .latencyCritical] // as an example
    activityToken = ProcessInfo.processInfo().beginActivityWithOptions(options, reason: "Your Good Reason")

    /* do some work */

    ProcessInfo.processInfo().endActivity(activityToken)
}

Me personally - I didn't want to endActivity. Never. I am a bad boy, I know, but the idea of this application is to have it at full power all the time. So I have omitted the return value of the beginActivityWithOptions method thinking that it works as a trigger, as well as not calling endActivity() method. But no. I was wrong.

You have to keep the returning object for as long as you want App Nap feature to be disable.

After I have done this with a class property to which I assign the returning object - the system stopped putting my app into a nap mode. Profit!

Goodies

There is another cool method you should consider using: performActivity(options:reason:using:).
This method is used with a closure where you put your stuff that has to be done without being interrupted by the nap mode. As soon as the closure returns - activity process is being terminated and the system can put your app into the nap mode.

Conclusion

Sometimes this might be necessary but you shouldn't abuse this class, be a good citizen, preserve Mac's battery by allowing the system to put your app into a nap.

Comments

comments powered by Disqus