Wednesday, September 10, 2025
HomeiOS Development@preconcurrency utilization in swift defined – Donny Wals

@preconcurrency utilization in swift defined – Donny Wals


Whenever you allow strict concurrency checks to your present tasks, it’s doubtless that Xcode will current a great deal of warnings and/or errors whenever you compile your undertaking for the primary time. On this submit, I’d like to try a selected sort of error that pertains to code that you just didn’t write.

The @preconcurrency declaration will be added to:

  • features
  • 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 are able to’t replace all of our dependencies simply but.

@preconcurrency imports

To be particular, Xcode will generally provide a message that reads so much like this:

Add @preconcurrency to suppress Sendable-related warnings from module MyModule

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 won’t be a module that you just personal, Xcode affords you the flexibility 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 must be suppressed.

If MyModule shouldn’t be a module that you just personal, it makes a whole lot of sense to suppress warnings; you possibly can’t repair them anyway.

Be aware that this received’t suppress warnings associated to code from MyModule that is Sendable or up-to-date with trendy concurrency. So if you happen to 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, features, and extra

Alternatively, you is likely to be 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 depends upon your module doesn’t break.

Adopting Swift Concurrency will imply that your module’s ABI modifications and that some older code won’t have the ability to use your modules if that older code doesn’t additionally undertake Swift Concurrency.

If that is the scenario you’re in, you might need up to date a few of your code from this:

public class CatalogViewModel {
  public personal(set) var books: [Book] = []

  public init() {}

  func loadBooks() {
    // load books
  }
}

To this:

@MainActor
public last class CatalogViewModel {
  public personal(set) var books: [Book] = []

  public init() {}

  public func loadBooks() {
    // load books
  }
}

When 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 are able to’t use our view mannequin except we dispatch to the principle actor ourselves. The compiler will present an error that appears a bit like this:

Name to principal actor-isolated initializer ‘init()’ in a synchronous nonisolated context.
Name to principal actor-isolated occasion methodology ‘loadBooks()’ in a synchronous nonisolated context.

This tells us that with a purpose to work together with CatalogViewModel, we’ll must replace our undertaking to make use of the principle actor. This can usually snowball into an increasing number of code updates which makes the modifications 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 principal actor annotated:

@preconcurrency @MainActor 
public last class CatalogViewModel {
  public personal(set) var books: [Book] = []

  public init() {}

  public func loadBooks() {
    // load books
  }
}

Be aware that the above solely works for tasks 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 tasks which have their concurrency checking set to minimal. If you happen to’re utilizing strict concurrency checks, the compiler will nonetheless emit errors for not utilizing CatalogViewModel with the principle actor.

In Abstract

With @preconcurrency, we are able to import outdated modules into new code and we are able to permit utilization of recent code in outdated tasks. It’s an effective 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 whenever 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 inconceivable to make use of them in non-concurrent code could make a whole lot of sense for library authors.

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments