search by tags

for the user

adventures into the land of the command line

swift 2 gcd cheatsheet

Is grand central dispatch iOS’s asynchronous message control bus? To be honest I don’t know how to use it skillfully or even describe it properly, but I’ll try anyway.

Say you want to get your app to call an API, what would happen in a synchronous request is while your app is waiting for the API response to come back from the internet, it’s user interface will freeze. This is bad, cos the user will be like “What the eff? This app sucks”.

So what people do instead is they use asynchronous requests. While waiting for things that are out of it’s control, like a response from another server’s API, the CPU will go and do other things, like keep the UI interactive, and when the response comes back, the CPU will go back to it, alternating between different jobs instead of focusing on one thing at a time. It all happens so fast, to a human being it seems like its happening simultaneously.

If only I could do this in real life too! Uggh

So GCD is the name for the collective libraries and functions allowing you to work with asynchronous and synchronous requests. Here’s my GCD cheatsheet:

GCD works with first-in first-out (FIFO) queues. There are three queues:

The main queue. This is on the main thread and is the one that also updates the UI.

Concurrent (Public) queues. These are asynchronous queues with four levels of priority.
The four levels of priority are:
1. QOS_CLASS_USER_INTERACTIVE. Tasks that need to be done immediately.
2. QOS_CLASS_USER_INITIATED. Tasks initiated from the UI but can be done asynchronously.
3. QOS_CLASS_UTILITY. For long running background tasks that the user should be aware of.
4. QOS_CLASS_BACKGROUND. For long running background tasks that the user does not necessarily need be aware of.

Serial (Private) queues. These are synchronous queues. You can create your own ones for ad-hoc purposes.

Asynchronous Functions

Use an asynchronous thread with the main queue.

dispatch_async(dispatch_get_main_queue()) {
  ...
}

Create a delay and tell the thread to do something on the main queue after the delay.

let delay = 5 * Double(NSEC_PER_SEC)
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
dispatch_after(time, dispatch_get_main_queue()) {
  ...
}

Use an asynchronous thread with a concurrent queue. Use the highest priority concurrent queue.

dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0)) {
  ...
}

Create a semaphore. The semaphore allows you to signal to an asynchronous thread to stop here, and start again here. In the example, the first asynchronous request should complete before the seconds one starts, as the semaphore is waiting before the pointer can get to the second one. When the first request finishes, the dispatch_semaphore_signal tells GCD to carry on from the point it was waiting at before.

let semaphore = dispatch_semaphore_create(0)
dispatch_async(dispatch_get_main_queue()) {
    someHTTPrequest {
      ...
      dispatch_semaphore_signal(semaphore)
    }
}

dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
dispatch_async(dispatch_get_main_queue()) {
    someOtherHTTPrequest {
      ...
    }
}

Synchronous Functions

Create a custom serial queue.

let mySerialLoginQueue = dispatch_queue_create("com.myFancyQueue.mySerialLoginQueue", DISPATCH_QUEUE_SERIAL)
dispatch_sync(mySerialLoginQueue) {
  ...
}