Revealed on: July 31, 2024
When you begin migrating to the Swift 6 language mode, you will more than likely activate strict concurrency first. As soon as you’ve got accomplished this there will probably be a number of warings and errors that you will encounter and these errors could be complicated at instances.
I will begin by saying that having a stable understanding of actors, sendable, and knowledge races is a large benefit once you wish to undertake the Swift 6 language mode. Just about the entire warnings you will get in strict concurrency mode will inform you 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 can get you entry to a sequence of movies, workouts, and my Sensible Swift Concurrency ebook with a single buy.
WIth that out of the way in which, let’s check out the next warning that you simply may encounter in your challenge:
Reference to captured var in concurrently-executing code
This warning tells you that you simply’re capturing a variable within a physique of code that can run asynchornously. For instance, the next code will end result on this warning:
var activity = NetworkTask(
urlsessionTask: urlSessionTask
)
add(fromTask: urlSessionTask, metaData: metaData, completion: { end in
Job {
await activity.sendResult(end result) // Reference to captured var 'activity' in concurrently-executing code; that is an error within the Swift 6 language mode
}
})
The activity
variable that we create a few traces earlier is mutable. Because of this we are able to assign a special worth to that activity at any time and that would end in inconsistencies in our knowledge. For instance, if we assign a brand new worth to the activity
earlier than the closure begins working, we’d have captured the previous activity
which might be surprising.
Since strict concurrency is supposed to assist us ensure that our code runs as freed from surprises as doable, Swift desires us to ensure that we seize a continuing worth as an alternative. On this case, I am not mutating activity
anyway so it is secure to make it a let
:
let activity = NetworkTask(
urlsessionTask: urlSessionTask
)
add(fromTask: urlSessionTask, metaData: metaData, completion: { end in
Job {
await activity.sendResult(end result)
}
})
This alteration removes the warning as a result of the compiler now is aware of for certain that activity
will not be given a brand new worth at some surprising time.
One other approach to repair this error could be to make in specific 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 is not going to change unexpectedly.
var activity = NetworkTask(
urlsessionTask: urlSessionTask
)
add(fromTask: urlSessionTask, metaData: metaData, completion: { [task] end in
Job {
await activity.sendResult(end result.mapError({ $0 as any Error }))
}
})
Altenatively, you can make an specific fixed seize earlier than your Job
runs:
var activity = NetworkTask(
urlsessionTask: urlSessionTask
)
let theTask = activity
add(fromTask: urlSessionTask, metaData: metaData, completion: { end in
Job {
await theTask.sendResult(end result)
}
})
This isn’t as elegant however could be wanted in circumstances the place you do wish to move your variable to a chunk of concurrently executing code however you additionally need it to be a mutable property for different objects. It is basically the very same factor as making a seize in your completion closure (or straight within the activity if there is not any further wrapping closures concerned).
Once you first encounter this warning it could be instantly apparent why you are seeing this error and the way you need to repair it. In digital all circumstances it implies that it is advisable both change your var
to a let
or that it is advisable carry out an specific seize of your variable both by making a shadowing let
or by means of a seize listing on the primary concurrent little bit of code that accesses your variable. Within the case of the instance on this put up that is the completion
closure however for you it could be straight on the Job
.