Calculate values in background and use the result after with Swift concurrency


If you need to compute a value and don’t want to block the main thread you can do so by calculating that value in a Swift Task structure that will return that computed value. Prior to Swift concurrency you would probably jump to a background queue and compute the value that you need and proceed with some action if necessary.

Let’s jump into an example. I defined a struct called Example that will create a Task at its init in which it will try to compute and return a String value. The struct will also have an async method called value() which will return that computed value.

struct Example {
  
  private var someTask: Task<String, Error> = Task {
    // Some calculation
    try await Task.sleep(nanoseconds: 3_000_000_000)
    return "example"
  }

  func value() async throws -> String {
    return try await someTask.value
  }
}

When we want to access the computed value we can use the value property that is defined on the Swift Task structure. If the task hasn’t completed, accessing this property waits for it to complete and its priority increases to that of the current task.

To use the Example structure we need to instantiate it and read the value from an async context:

let example = Example()

Task {
  do {
    print("Value is:", try await example.value())
  }
}

If the Task will not throw an error then its type would be Task<ReturnType, Never> and we wouldn’t need to use try keyword when accessing the task’s value.

This has helped me in some situation where I want to calculate something in advance and if user requests it that I instantly have it. For example, I wanted to compress the image from camera in case user presses the button to send the image. I start the compression on the image preview screen and then when user wants to send it I have the compressed image ready.

Join the discussion

comments powered by Disqus