Schedule Background Activity
Background activity includes periodic tasks that aren’t user-initiated or that aren’t blocking the user.
Schedule Deferrable Background Activities
The NSBackgroundActivityScheduler
API provides a simple interface for scheduling an arbitrary maintenance or background task. It’s similar to an NSTimer
object, in that it lets you schedule a repeating or nonrepeating task. However, NSBackgroundActivityScheduler
gives the system flexibility to determine the most efficient time to execute based on energy usage, thermal conditions, and CPU use.
Use the NSBackgroundActivityScheduler
API to schedule:
Automatic saves
Backups
Data maintenance
Periodic content fetches
Installation of updates
Activities occurring in intervals of 10 minutes or more
Any other deferrable tasks
Create a Scheduler
To initialize a scheduler, call initWithIdentifier:
for NSBackgroundActivityScheduler
, and pass it a unique identifier string in reverse DNS notation (nil
and zero-length strings are not allowed) that remains constant across launches of your application. See Listing 12-1.
Objective-C
NSBackgroundActivityScheduler *activity = [[NSBackgroundActivityScheduler alloc] initWithIdentifier:@"com.example.MyApp.updatecheck"];
Swift
let activity = NSBackgroundActivityScheduler(identifier: "com.example.MyApp.updatecheck")
Configure Scheduler Properties
Configure the scheduler with the desired scheduling properties.
repeats
—If set toYES
true
, the activity is rescheduled at the specified interval after finishing.interval
—For repeating schedulers, the average interval between invocations of the activity. For non-repeating schedulers,interval
is the suggested interval of time between scheduling the activity and the invocation of the activity.tolerance
—The amount of time before or after the nominal fire date when the activity should be invoked. The nominal fire date is calculated by using the interval combined with the previous fire date or the time when the activity is started. These two properties create a window in time, during which the activity may be scheduled. The system will more aggressively schedule the activity as it nears the end of the grace period after the nominal fire date. The default value is half the interval.qualityOfService
—The default value isNSQualityOfServiceBackground
. If you upgrade the quality of service above this level, the system schedules the activity more aggressively. The default value is the recommended value for most activities. For information on quality of service, see Prioritize Work at the Task Level.
Listing 12-2, Listing 12-3, and Listing 12-4 demonstrate different scheduling scenarios.
Objective-C
activity.tolerance = 10 * 60;
Swift
activity.tolerance = 10 * 60
Objective-C
activity.interval = 30 * 60;
activity.tolerance = 15 * 60;
Swift
activity.interval = 30 * 60
activity.tolerance = 15 * 60
Objective-C
activity.repeats = YES;
activity.interval = 60 * 60;
Swift
activity.repeats = true
activity.interval = 60 * 60
Schedule Activity with scheduleWithBlock:
When you’re ready to schedule the activity, call scheduleWithBlock:
and provide a block of code to execute when the scheduler runs, as shown in Listing 12-5. The block will be called on a serial background queue appropriate for the level of quality of service specified. The system automatically uses the beginActivityWithOptions:reason:
method (of NSProcessInfo
) while invoking the block, choosing appropriate options based on the specified quality of service.
When your block is called, it’s passed a completion handler as an argument. Configure the block to invoke this handler, passing it a result of type NSBackgroundActivityResult
to indicate whether the activity finished (NSBackgroundActivityResultFinished
) or should be deferred (NSBackgroundActivityResultDeferred
) and rescheduled for a later time. Failure to invoke the completion handler results in the activity not being rescheduled. For work that will be deferred and rescheduled, the block may optionally adjust scheduler properties, such as interval
or tolerance
, prior to calling the completion handler.
Objective-C
[activity
scheduleWithBlock:^(NSBackgroundActivityCompletionHandler completion) {
// Perform the activity
self.completion(NSBackgroundActivityResultFinished);
}];
Swift
activity.scheduleWithBlock() { (completion: NSBackgroundActivityCompletionHandler) in
// Perform the activity
self.completion(NSBackgroundActivityResult.Finished)
}
Detect Whether to Defer Activity
It’s conceivable that while a lengthy activity is running, conditions may change, resulting in the activity now requiring deferral. For example, perhaps the user has unplugged the Mac and it’s now running on battery power. Your activity can call shouldDefer
to determine whether this has occurred. A value of YES
true
indicates that the block should finish up what it’s currently doing and invoke its completion handler with a value of NSBackgroundActivityResultDeferred
. See Listing 12-6.
Objective-C
if ([activity shouldDefer]) {
// Wrap up processing and prepare to defer activity
self.completion(NSBackgroundActivityResultDeferred);
} else {
// Continue processing
self.completion(NSBackgroundActivityResultFinished);
};
Swift
if activity.shouldDefer {
// Wrap up processing and prepare to defer activity
self.completion(NSBackgroundActivityResult.Deferred)
} else {
// Continue processing
self.completion(NSBackgroundActivityResult.Finished)
}
Stop Activity
Call invalidate
to stop scheduling an activity, as shown in Listing 12-7.
Objective-C
[activity invalidate];
Swift
activity.invalidate()
Specify Nondeferrable Background Activities
If your app performs background work that can’t be deferred, call either beginActivityWithOptions:reason:
(Listing 12-8) or performActivityWithOptions:reason:usingBlock:
(Listing 12-9) and pass the NSActivityBackground
constant. Doing so lets the system know that the work your app is performing is important, and helps with the prioritization and management of other tasks that may be occurring at the same time.
Objective-C
NSOperationQueue *myQueue = [[NSOperationQueue alloc] init];
id myBackgroundActivity = [[NSProcessInfo processInfo]
beginActivityWithOptions: NSActivityBackground
reason: @"Doing important background work"];
[myQueue addOperationWithBlock:^{
// Do important background work here
[[NSProcessInfo processInfo] endActivity:myBackgroundActivity];
}];
Swift
let myQueue = NSOperationQueue()
let myBackgroundActivity = NSProcessInfo.processInfo()
myBackgroundActivity.beginActivityWithOptions(NSActivityOptions.Background,
reason: "Doing important background work")
myQueue.addOperationWithBlock() {
// Do important background work here
NSProcessInfo.processInfo().endActivity(myBackgroundActivity)
}
Objective-C
[[NSProcessInfo processInfo] performActivityWithOptions: NSActivityBackground
reason: @"Performing important background work."
usingBlock: ^{
// Do important background work here
}
];
Swift
NSProcessInfo.processInfo().performActivityWithOptions(NSActivityOptions.Background,
reason: "Performing important background work.") {
// Do important background work here
}
Copyright © 2018 Apple Inc. All rights reserved. Terms of Use | Privacy Policy | Updated: 2016-09-13