Swift Concurrency Cheat Sheet

loading views

Actors

  • Only one task can execute on an actor at a time
    • Other tasks must wait their turn

Sendable

  • Code has to conform to Sendable whenever it crosses actor boundaries.

Isolation

  • Non-isolated async code executes on the cooperative pool (Reference)
  • Non-isolated synchronous code executes wherever it is called (Reference)
  • In SwiftUI only body is @MainActor isolated. It's recommended to explicitly conform all SwiftUI views to @MainActor

How to execute an expensive synchronous function outside of the MainActor?

Solution #1: nonisolated-conformance

Conform it to nonisolated and mark is as async. This has the advantage of running on the cooperative thread pool, so many instances of this function can run in parallel.

nonisolated func convertToJPEG(url: URL) async -> Data {
    ImageConverter.convert(url ,to: .jpeg)
}

Solution #2: use global actor

Conform it to a custom global actor. Disadvantage is that the actor can execute only one task at a time.

// Create custom global actor
@globalActor
actor ImageConverterActor {
    static let shared = ImageConverterActor()
}

@ImageConverterActor
enum ImageConverter {
    static func convert(_ url: URL, to: ImageType) -> Data {
        ...
    }
}