NSQualityOfService

Any Cocoa developer worth his macbook knows a thing or two about concurrent (or multi-threaded) programming. From POSIX threads to Grand Central Dispatch, to NSOperationQueue, to closures and callbacks, there's no shortage of options for doing asynchronous work in Cocoa.

Multi-threaded programming isn't just for Mac Pros and server applications, it's an essential component of any well-built mobile app, and for good reason: blocking the main thread, even for something as simple as loading an array of images from your bundle, will lock up your user interface and could make your app unresponsive.

iOS devices use power most efficiently when they're able to group a bunch of tasks together, perform the tasks, then power the chip down to an idle state. What this means, practically speaking, is if you use a background services entitlement to run a HTTP request on a timer, you'll need to burn CPU cycles 100% of the time, whereas if you schedule your tasks with the system's NSURLSession background queue, then every app on the phone that needs to do an HTTP fetch will all power up and fetch together, conserving battery and giving developers a clean, simple way to keep their app in sync with their server.

NSOperationQualityOfService is a way for your to specify the type of work you're going to be performing on a given queue, and the system will manage power and resources accordingly. This includes differentiating between user-initiated tasks and user-interaction tasks, but also provides a sane default for utility tasks and low-priority background tasks.

Don't make the mistake of thinking your app is so good that it deserves to run 24hrs/day at full power on the main thread. Be a good citizen of the platform, and your users will thank you.

To implement NSOperationQualityOfService, you just create an NSOperationQueue as normal, but set its qualityOfService property to one of the following constants:

NSOperationQualityOfServiceUserInteractive The operation corresponds to a graphically interactive task, involving scrolling or animation in some form. Because they are user interactive, operations with this service level are given the highest priority for any needed system resources.

NSOperationQualityOfServiceUserInitiated The operation corresponds to a task that the user initiated. Tasks with this service level are given a relatively high priority for system resources because they were initiated by the user and therefore correspond to work the user wants done soon.

NSOperationQualityOfServiceUtility The operation corresponds to tasks initiated by the app but reflecting relatively important work being done on behalf of the user. Tasks with this service level are given a medium priority for system resources.

NSOperationQualityOfServiceBackground The operation corresponds to tasks that are initiated by the app and represent noncritical tasks. Operations with this priority are given the lowest priority for system resources.

One of the neat features of qualityOfService is that operationQueues and operations both have their own qualityOfService properties.

Say we have an app that downloads JSON from a web server, parses the JSON into NSManagedObjects, then saves them to the CoreData database on the user's device. When our app is in the background, there's no rush to process that incoming data, so Utility or even Background would be appropriate qualityOfService levels for the JSON dowloading operation. When the app is running, however, we want to update the UI as soon as the parsed JSON data is available. You can create the JSON fetch operation the same way for both scenarios, but when you add that operation to an NSOperationQueue with a QoS level of userInteractive, the operation automatically gets upgraded to a userInteractive QoS level. Prtty cool huh?

NSOperationQualityOfService is available on iOS8, so go play around with it and see if you can make your apps more responsive and more considerate of the user's device. Check out the NSOperation Class Reference for more details on Quality of Service, and be sure to watch the 2 outstanding WWDC 2014 sessions on Writing Energy Efficient Code