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
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
MainActor
?
How to execute an expensive synchronous function outside of the 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 {
...
}
}