Documentation Archive

Developer

Energy Efficiency Guide for Mac Apps

On This Page

Defer Tasks with XPC Activity

The XPC Activity API is a C-level interface that can be used to request centralized scheduling of discretionary tasks in your app. XPC Activity is part of XPC (see activity.h Reference in XPC Services API Reference), a low-level interprocess communication mechanism in OS X.

Use the XPC Activity API to tell the system when you have work that can be deferred, how long it can be deferred, and whether it should be deferred until the computer is plugged into power.

Whenever possible, especially when your users are on battery power, defer execution of low priority discretionary tasks such as:

  • Cleaning up temporary files

  • Syncing data

  • Indexing document content

  • Checking for updated versions of your software (if your app is not distributed through the Mac App Store)

  • Downloading updates (if your app is not distributed through the Mac App Store)

For detailed information about XPC Services, refer to Daemons and Services Programming Guide.

XPC Activity Constants

To use the XPC Activity API, you register with XPC and provide a dictionary that specifies a set of activity properties. The following properties are especially useful for scheduling discretionary tasks:

  • XPC_ACTIVITY_ALLOW_BATTERY. Boolean value indicating whether the activity should be allowed to run while the computer is on battery power.

    XPC_ACTIVITY_ALLOW_BATTERY defaults to YEStrue for utility-level activities and NOfalse for maintenance-level activities, but the constant can be overridden in either case.

  • XPC_ACTIVITY_DELAY. The number of seconds to delay before beginning the activity.

  • XPC_ACTIVITY_GRACE_PERIOD. The number of seconds to allow as a grace period before the scheduling of the activity becomes more aggressive.

  • XPC_ACTIVITY_REPEATING. Boolean value indicating whether the activity should be automatically rescheduled after it completes.

  • XPC_ACTIVITY_INTERVAL. The number of seconds between repeating or delayed intervals.

  • XPC_ACTIVITY_PRIORITY_MAINTENANCE. Maintenance-level priority. Maintenance priority is intended for user-invisible maintenance tasks such as garbage collection or optimization.

  • XPC_ACTIVITY_PRIORITY_UTILITY. Utility-level priority. Utility priority is intended for user-visible tasks such as fetching data from the network, copying files, or importing data.

For a complete list of properties, see Global Constants in activity.h Reference.

Example of Simple XPC Activity Use

The code in Listing 14-1 defines and registers an XPC dictionary specifying a discretionary maintenance activity that can be delayed from 1 to 12 hours. Based on this dictionary, XPC runs the block of code that performs the activity in its own queue at an appropriate time that doesn’t interfere with the user’s battery life.

Listing 14-1Allowing a discretionary activity to be deferred for 12 hours

Objective-C

  1. // Create an empty XPC dictionary
  2. xpc_object_t criteria = xpc_dictionary_create(NULL, NULL, 0);
  3. // Tell XPC that this is a non-repeating activity
  4. xpc_dictionary_set_bool(criteria, XPC_ACTIVITY_REPEATING, FALSE);
  5. // The activity should start in 1 hour (3600 seconds)
  6. xpc_dictionary_set_int64(criteria, XPC_ACTIVITY_DELAY, XPC_ACTIVITY_INTERVAL_1_HOUR);
  7. // Allow XPC to defer the activity by as much as 12 hours
  8. xpc_dictionary_set_int64(criteria, XPC_ACTIVITY_GRACE_PERIOD, 12 * XPC_ACTIVITY_INTERVAL_1_HOUR);
  9. // Indicate that this is a user-invisible activity
  10. xpc_dictionary_set_string(criteria,XPC_ACTIVITY_PRIORITY, XPC_ACTIVITY_PRIORITY_MAINTENANCE);
  11. // Register the new XPC dictionary and pass it the handler block that performs the activity
  12. xpc_activity_register("com.myapp.MySimpleActivity", criteria, ^(xpc_activity_t activity)
  13. {
  14. /* do background or deferred work here */
  15. }
  16. );

Swift

  1. import XPC
  2. // Create an empty XPC dictionary
  3. var criteria = xpc_dictionary_create(nil, nil, 0)
  4. // Tell XPC that this is a non-repeating activity
  5. xpc_dictionary_set_bool(criteria, XPC_ACTIVITY_REPEATING, false)
  6. // The activity should start in 1 hour (3600 seconds)
  7. xpc_dictionary_set_int64(criteria, XPC_ACTIVITY_DELAY, XPC_ACTIVITY_INTERVAL_1_HOUR)
  8. // Allow XPC to defer the activity by as much as 12 hours
  9. xpc_dictionary_set_int64(criteria, XPC_ACTIVITY_GRACE_PERIOD, 12 * XPC_ACTIVITY_INTERVAL_1_HOUR)
  10. // Indicate that this is a user-invisible activity
  11. xpc_dictionary_set_string(criteria, XPC_ACTIVITY_PRIORITY, XPC_ACTIVITY_PRIORITY_MAINTENANCE)
  12. // Register the new XPC dictionary and pass it the handler block that performs the activity
  13. xpc_activity_register("com.myapp.MySimpleActivity", criteria) { (activity)
  14. /* do background or deferred work here */
  15. }
  16. )

XPC Activity State

XPC activities also possess a state attribute, which allows them to keep running after the activity’s handler block has returned.

Your app can check the current activity state by calling xpc_activity_get_state, and it can set the current activity state by calling xpc_activity_set_state. XPC activities support the following states:

  • XPC_ACTIVITY_STATE_CHECK_IN. An optional state indicating that the activity has just completed a checkin with the system after XPC_ACTIVITY_CHECK_IN was provided as the criteria parameter to xpc_activity_register. The state gives the app an opportunity to inspect and modify the activity's criteria.

  • XPC_ACTIVITY_STATE_WAIT. The activity is waiting for an opportunity to run. This value is never returned within the activity's handler block, as the block is invoked in response to XPC_ACTIVITY_STATE_CHECK_IN or XPC_ACTIVITY_STATE_RUN.

  • XPC_ACTIVITY_STATE_RUN. The activity is eligible to run based on its criteria. Your app shouldn’t attempt to set this state, as it occurs automatically.

  • XPC_ACTIVITY_STATE_DEFER. The activity should be deferred (placed back into the XPC_ACTIVITY_STATE_WAIT state) until a time when its criteria are met again.

  • XPC_ACTIVITY_STATE_CONTINUE. The activity will continue its operation beyond the return of its handler block. This state can be used to extend an activity to include asynchronous operations. The activity's handler block will not be invoked again until the state has been updated to either XPC_ACTIVITY_STATE_DEFER or, in the case of repeating activity, XPC_ACTIVITY_STATE_DONE.

  • XPC_ACTIVITY_STATE_DONE. The activity has completed. For non-repeating activity, the resources associated with the activity will be automatically released upon return from the handler block. For repeating activity, timers present in the activity's criteria will be reset. Your app shouldn’t attempt to set this state, as it occurs automatically.