How do I disable app nap in Swift? Im new to programming and I am building a timer(just for practice), and I am afraid app nap will break my timer.
-
Not sure what the app nap is but are you looking for [idleTimerDisabled](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplication_Class/index.html#//apple_ref/occ/instp/UIApplication/idleTimerDisabled)? – Desdenova Dec 26 '14 at 12:50
-
idleTimerDisabled seems to only work on iOS App. Mine is OSX application. AppNap is a technology that apple introduced with Mavericks OS X to low energy consumption – Vitor Loureiro Dec 26 '14 at 18:30
-
My bad, didn't notice OS X tag. – Desdenova Dec 27 '14 at 10:37
4 Answers
I found that this solution works in Swift as well.
Create a class or global variable
var activity: NSObjectProtocol?
And assign it after which App Nap will be disabled
activity = NSProcessInfo().beginActivityWithOptions(NSActivityOptions.UserInitiated, reason: "Good Reason")
Swift 3:
var activity: NSObjectProtocol?
and
activity = ProcessInfo().beginActivity(options: ProcessInfo.ActivityOptions.userInitiated, reason: "Good Reason")

- 412
- 6
- 10
Swift 4.x / 5.3:
For ProcessInfo.ActivityOptions
, Apple's documentation describes:
static var userInitiated
Flag to indicate the app is performing a user-requested action.
static var userInitiatedAllowingIdleSystemSleep
Flag to indicate the app is performing a user-requested action, but that the system can sleep on idle.
Unless your intention is to prevent the system from sleeping, you should use userInitiatedAllowingIdleSystemSleep
.
Steps
Retain reference in a scope that will survive until any point you may want to revert the change (ie: within
AppDelegate
)var activity: NSObjectProtocol?
Run this, possibly in AppDelegate
applicationDidFinishLaunching
:activity = ProcessInfo.processInfo.beginActivity(options: .userInitiatedAllowingIdleSystemSleep, reason: "Good Reason")
To cancel and re-enable App Nap at any time:
if let pinfo = activity {
ProcessInfo.processInfo.endActivity(pinfo)
}

- 952
- 10
- 15
None of the previous 3 answers to this question correctly use ProcessInfo
class. As per ProcessInfo
documentation:
Each process has a single, shared
ProcessInfo
object, known as a process information agent. TheprocessInfo
type property [previously class method] returns the shared agent for the current process.
processInfo
documentation explains it further:
The object is created the first time this property [previously method] is invoked, and that same object is returned on each subsequent invocation.
Otherwise you refer to different instances of ProcessInfo
object when beginning and ending activity (you must end activity), what can lead to incorrect behaviour. Thus the correct code in Swift 5 is:
let activity = ProcessInfo.processInfo.beginActivity(options: .userInitiatedAllowingIdleSystemSleep, reason: "Timer")
// Perform some work
ProcessInfo.processInfo.endActivity(activity)
While the details of the app and timer implementation are unknown, it's hard to say whether this approach is correct in your case. Please also consider these notes:
If your activity takes place synchronously inside an event callback on the main thread, you do not need to use this API.
Be aware that failing to end these activities for an extended period of time can have significant negative impacts to the performance of your user's computer, so be sure to use only the minimum amount of time required. User preferences may override your application’s request.
Usage of Timer
object (and bringing in some tolerance if possible) may be a more correct approach. System (and its App Nap feature) should account for the timer. Testing and Activity Monitor will tell you.

- 153
- 1
- 6