Once you allow strict concurrency checks in your current initiatives, it’s probably that Xcode will current a great deal of warnings and/or errors while you compile your challenge for the primary time. On this put up, I’d like to check out a particular sort of error that pertains to code that you just didn’t write.
The @preconcurrency
declaration could be added to:
- capabilities
- sorts
- protocols
- imports
Let’s check out all of those areas to totally perceive how @preconcurrency
helps us allow strict concurrency checks even when we will’t replace all of our dependencies simply but.
@preconcurrency imports
To be particular, Xcode will typically provide a message that reads quite a bit like this:
Add
@preconcurrency
to suppressSendable
-related warnings from moduleMyModule
This error tells us that we’re importing a module that doesn’t seem to fully adhere to trendy concurrency guidelines simply but. Since this may not be a module that you just personal, Xcode presents you the power to silence strict concurrency warnings and errors coming from this module.
You are able to do this by including @preconcurrency
to your import
assertion:
@preconcurrency import MyModule
By doing this, Xcode will know that any warnings associated to sorts coming from MyModule
ought to be suppressed.
If MyModule
is just not a module that you just personal, it makes lots of sense to suppress warnings; you’ll be able to’t repair them anyway.
Notice that this gained’t suppress warnings associated to code from MyModule
that is Sendable
or up-to-date with trendy concurrency. So for those who see warnings associated to concurrency on a module that you just’ve marked with @preconurrency
, you’ll wish to repair these warnings as a result of they’re right.
Including @preconcurrency to sorts, capabilities, and extra
Alternatively, you is perhaps engaged on a module that has adopted Swift Concurrency and also you’ve mounted your warnings. If that’s the case, you may wish to add @preconcurrency
to a few of your declarations to make sure that code that will depend on your module doesn’t break.
Adopting Swift Concurrency will imply that your module’s ABI adjustments and that some older code may not have the ability to use your modules if that older code doesn’t additionally undertake Swift Concurrency.
If that is the state of affairs you’re in, you may need up to date a few of your code from this:
public class CatalogViewModel {
public non-public(set) var books: [Book] = []
public init() {}
func loadBooks() {
// load books
}
}
To this:
@MainActor
public closing class CatalogViewModel {
public non-public(set) var books: [Book] = []
public init() {}
public func loadBooks() {
// load books
}
}
If in case you have pre-concurrency code that makes use of this class, it would look a bit like this:
class TestClass {
func run() {
let obj = CatalogViewModel()
obj.loadBooks()
}
}
Sadly including @MainActor
to our class within the module makes it in order that we will’t use our view mannequin until we dispatch to the primary actor ourselves. The compiler will present an error that appears a bit like this:
Name to foremost actor-isolated initializer ‘init()’ in a synchronous nonisolated context.
Name to foremost actor-isolated occasion methodology ‘loadBooks()’ in a synchronous nonisolated context.
This tells us that to be able to work together with CatalogViewModel
, we’ll must replace our challenge to make use of the primary actor. This can usually snowball into an increasing number of code updates which makes the adjustments in our module severely breaking.
We are able to apply @preconcurrency
to our view mannequin to permit code that hasn’t been up to date to work together with our view mannequin as if it was by no means foremost actor annotated:
@preconcurrency @MainActor
public closing class CatalogViewModel {
public non-public(set) var books: [Book] = []
public init() {}
public func loadBooks() {
// load books
}
}
Notice that the above solely works for initiatives that don’t allow strict concurrency checking
With the @preconcurrency
annotation in place for our complete class, the compiler will strip the @MainActor
annotation for initiatives which have their concurrency checking set to minimal
. Should you’re utilizing strict concurrency checks, the compiler will nonetheless emit errors for not utilizing CatalogViewModel
with the primary actor.
In Abstract
With @preconcurrency
, we will import previous modules into new code and we will enable utilization of recent code in previous initiatives. It’s a good way to begin to incrementally undertake strict concurrency as the discharge of Swift 6 comes nearer and nearer.
Including @preconcurrency
to your imports could be very helpful while you’re importing modules that haven’t but been up to date for strict concurrency.
Including @preconcurrency
to declarations that you just’ve annotated as @Sendable
, @MainActor
, or in any other case up to date in a method that makes it unimaginable to make use of them in non-concurrent code could make lots of sense for library authors.