Printed on: July 31, 2024
When you begin migrating to the Swift 6 language mode, you will almost certainly activate strict concurrency first. As soon as you’ve got performed this there shall be a number of warings and errors that you will encounter and these errors may be complicated at occasions.
I will begin by saying that having a stable understanding of actors, sendable, and knowledge races is a big benefit if you need to undertake the Swift 6 language mode. Just about all the warnings you will get in strict concurrency mode will let you know about potential points associated to working code concurrently. For an in-depth understanding of actors, sendability and knowledge races I extremely suggest that you simply check out my Swift Concurrency course which is able to get you entry to a sequence of movies, workout routines, and my Sensible Swift Concurrency guide with a single buy.
WIth that out of the best way, let’s check out the next warning that you simply may encounter in your undertaking:
Reference to captured var in concurrently-executing code
This warning tells you that you simply’re capturing a variable inside a physique of code that can run asynchornously. For instance, the next code will outcome on this warning:
var job = NetworkTask<Int, URLSessionUploadTask>(
urlsessionTask: urlSessionTask
)
add(fromTask: urlSessionTask, metaData: metaData, completion: { end in
Job {
await job.sendResult(outcome) // Reference to captured var 'job' in concurrently-executing code; that is an error within the Swift 6 language mode
}
})
The job
variable that we create a few traces earlier is mutable. Which means we will assign a unique worth to that job at any time and that might end in inconsistencies in our knowledge. For instance, if we assign a brand new worth to the job
earlier than the closure begins working, we’d have captured the outdated job
which could possibly be surprising.
Since strict concurrency is supposed to assist us be sure that our code runs as freed from surprises as potential, Swift needs us to be sure that we seize a relentless worth as an alternative. On this case, I am not mutating job
anyway so it is protected to make it a let
:
let job = NetworkTask<Int, URLSessionUploadTask>(
urlsessionTask: urlSessionTask
)
add(fromTask: urlSessionTask, metaData: metaData, completion: { end in
Job {
await job.sendResult(outcome)
}
})
This modification removes the warning as a result of the compiler now is aware of for certain that job
will not be given a brand new worth at some surprising time.
One other approach to repair this error could be to make in express seize within the completion
closure that I am passing. This seize will occur instantly as a let
so Swift will know that the captured worth won’t change unexpectedly.
var job = NetworkTask<Int, URLSessionUploadTask>(
urlsessionTask: urlSessionTask
)
add(fromTask: urlSessionTask, metaData: metaData, completion: { [task] end in
Job {
await job.sendResult(outcome.mapError({ $0 as any Error }))
}
})
Altenatively, you could possibly make an express fixed seize earlier than your Job
runs:
var job = NetworkTask<Int, URLSessionUploadTask>(
urlsessionTask: urlSessionTask
)
let theTask = job
add(fromTask: urlSessionTask, metaData: metaData, completion: { end in
Job {
await theTask.sendResult(outcome)
}
})
This isn’t as elegant however may be wanted in circumstances the place you do need to cross your variable to a chunk of concurrently executing code however you additionally need it to be a mutable property for different objects. It is primarily the very same factor as making a seize in your completion closure (or immediately within the job if there isn’t any additional wrapping closures concerned).
While you first encounter this warning it may be instantly apparent why you are seeing this error and the way it’s best to repair it. In digital all circumstances it signifies that it’s good to both change your var
to a let
or that it’s good to carry out an express seize of your variable both by making a shadowing let
or via a seize checklist on the primary concurrent little bit of code that accesses your variable. Within the case of the instance on this submit that is the completion
closure however for you it may be immediately on the Job
.