Sync and async code in Swift
Tags: sync, async, swift, ios
Published: 2018-09-21 19:37:43

---
title: Sync and async code in Swift
published: true
description: 
tags: sync, async, swift, ios
---

![](https://cdn-images-1.medium.com/max/1600/0*HevKOVykUzRprufo)

We should use DispatchQueue to build thread safe code. The idea is to prevent two read and writefrom happening at the same time from 2 different threads, which cause data corruption and unexpected behaviors. Note that you should try to avoid deadlock [stackoverflow.com/questions/15381209/how-do-i-create-a-deadlock-in-grand-central-dispatch](https://stackoverflow.com/questions/15381209/how-do-i-create-a-deadlock-in-grand-central-dispatch)

## All sync

Use try catch, together with serial queue. Use sync function to block current queue.

    func getUser(id: String) throws -> User {
      var user: User!
      try serialQueue.sync {
        user = try storage.getUser(id)
      }

      return user
    }

    func setUser(_ user: User) throws {
      try serialQueue.sync {
        try storage.setUser(user)
      }
    }

## All async

Use Result, toget with serial queue. Use async function to return to current queue.

    enum Result<T> {
      case value(T)
      case error(Error)
    }

    func getUser(id: String, completion: (Result<User>) - Void) {
      try serialQueue.async {
        do {
          user = try storage.getUser(id)
          completion(.value(user))
        } catch {
          completion(.error(error))
        }
      }

      return user
    }

    func setUser(_ user: User, completion: (Result<()>) -> Void) {
      try serialQueue.async {
        do {
          try storage.setUser(user)
          completion(.value(())
        } catch {
          completion(.error(error))
        }
      }
    }

## Sync read, async write

Use try catch for read, Result for write, together with concurrent queue. Use sync function for read to block current thread, while using async function with barrier flag for write to return to current queue. This is good for when multiple reads is preferred when there is no write. When write with barrier comes into the queue, other operations must wait.

    func getUser(id: String) throws -> User {
      var user: User!
      try concurrentQueue.sync {
        user = try storage.getUser(id)
      }

      return user
    }

    func setUser(_ user: User, completion: (Result<()>) -> Void) {
      try concurrentQueue.async(flags: .barrier) {
        do {
          try storage.setUser(user)
          completion(.value(())
        } catch {
          completion(.error(error))
        }
      }
    }

## Testing for asynchrony

Before we could use [dispatch_apply](https://developer.apple.com/documentation/dispatch/1453050-dispatch_apply) to submits a block to a dispatch queue for multiple invocations. Starting with Swift, the equivalence is [concurrentPerform](https://developer.apple.com/documentation/dispatch/dispatchqueue/2016088-concurrentperform)

    DispatchQueue.concurrentPerform(iterations: 1000) { index in
        let last = array.last ?? 0
        array.append(last + 1)
    }

## Reference

* [http://basememara.com/creating-thread-safe-arrays-in-swift](http://basememara.com/creating-thread-safe-arrays-in-swift/)

* [oleb.net/blog/2013/07/parallelize-for-loops-gcd-dispatch_apply](https://oleb.net/blog/2013/07/parallelize-for-loops-gcd-dispatch_apply/)

Original post https://medium.com/fantageek/sync-and-async-code-in-swift-8e6bc7bd5866

❤️ Support my apps ❤️ 

- [Push Hero - pure Swift native macOS application to test push notifications](https://onmyway133.com/pushhero)
- [PastePal - Pasteboard, note and shortcut manager](https://onmyway133.com/pastepal)
- [Quick Check - smart todo manager](https://onmyway133.com/quickcheck)
- [Alias - App and file shortcut manager](https://onmyway133.com/alias)
- [My other apps](https://onmyway133.com/apps/)

❤️❤️😇😍🤘❤️❤️