Swift Concurrency Cheat Sheet
Actors
- Only one task can execute on an actor at a time
- Other tasks must wait their turn
Sendable
- Code has to conform to
Sendablewhenever 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
bodyis@MainActorisolated. 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 {
...
}
}