Multi threading and concurrency are essential for the modern app …and yet Grand Central Dispatch, the system level library for managing concurrent operations, has one of the more cumbersome and unfriendly APIs in the iOS SDK.
Swift 3 brings with it many improvements to Grand Central Dispatch syntax and usage. This is a quick look at some of what’s new.
Previously, we would choose the dispatch method (sync vs async) and then the queue we wanted to dispatch our task to. The updated GCD reverses this order - we first choose the queue and then apply a dispatch method.
One of the most common GCD patterns is to perform work on a global background queue and update the UI on the main queue as soon as the work is done. This is what it looks like with the new API:
You will notice that queues now take attributes on init. This is a Swift OptionSet and can include queue options such as serial vs concurrent, memory and activity management options and the quality of service (.default, .userInteractive, .userInitiated, .utility and .background).
The quality of service replaces the old priority attributes that were deprecated in iOS8. If you were used to priority queues, here’s how they map over to QOS cases:
* DISPATCH_QUEUE_PRIORITY_HIGH: .userInitiated
* DISPATCH_QUEUE_PRIORITY_DEFAULT: .default
* DISPATCH_QUEUE_PRIORITY_LOW: .utility
* DISPATCH_QUEUE_PRIORITY_BACKGROUND: .background
The memory and activity management options are new for this year’s Apple OS releases (OSX 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0). These include the ability to start a queue in an inactive state with .initiallyInactive or set a custom autorelease setting for your queue with .autoreleaseInherit, .autoreleaseNever and .autoreleaseWorkItem.
Queues are not the only part of GCD to get a Swift OptionSet. There’s an updated Swift syntax for work items too:
A work item can now declare a quality or service and/or flags on init. Both of these are optional and affect the execution of the work item. The flags are an option set that includes the following options: barrier, detached, assignCurrentContext, noQoS, inheritQoS, enforceQoS.
dispatch_once was very useful for initialisation code and other functions that were to be executed once and only once.
In Swift 3, dispatch_once is deprecated and should be replaced with either global or static variables and constants.
dispatch_time_t was a function that translated a specified time to a UInt64 that could be provided to a queue. The updated GCD introduces a much friendlier syntax for this (farewell NSEC_PER_SEC). Here is an example with dispatch after:
The .seconds is part of a new enum called DispatchTimeInterval. The cases have an associated value representing the count. It currently supports:
Also new in this year’s Apple OS releases are dispatch preconditions. These replace dispatch_assert and allow you to check whether or not you are on the expected thread before executing code. This is particularly useful for functions that update the UI and must be executed on the main queue. Here’s a simple example:
There are many more GCD improvements included in Swift 3 but the official documentation is still incomplete at the time of writing. To go deeper: