Printed on: July 31, 2024
When you begin migrating to the Swift 6 language mode, you may most probably activate strict concurrency first. As soon as you’ve got completed this there shall be a number of warings and errors that you’re going to encounter and these errors may be complicated at instances.
I will begin by saying that having a strong understanding of actors, sendable, and information races is a big benefit once you need to undertake the Swift 6 language mode. Just about the entire warnings you may 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 information 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 e book with a single buy.
WIth that out of the way in which, let’s check out the next warning that you simply would possibly encounter in your undertaking:
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 process = NetworkTask(
urlsessionTask: urlSessionTask
)
add(fromTask: urlSessionTask, metaData: metaData, completion: { end in
Activity {
await process.sendResult(end result) // Reference to captured var 'process' in concurrently-executing code; that is an error within the Swift 6 language mode
}
})
The process
variable that we create a few strains earlier is mutable. Which means we are able to assign a distinct worth to that process at any time and that might end in inconsistencies in our information. For instance, if we assign a brand new worth to the process
earlier than the closure begins working, we would have captured the outdated process
which may very well be sudden.
Since strict concurrency is supposed to assist us ensure that our code runs as freed from surprises as attainable, Swift desires us to ensure that we seize a continuing worth as a substitute. On this case, I am not mutating process
anyway so it is protected to make it a let
:
let process = NetworkTask(
urlsessionTask: urlSessionTask
)
add(fromTask: urlSessionTask, metaData: metaData, completion: { end in
Activity {
await process.sendResult(end result)
}
})
This modification eliminates the warning as a result of the compiler now is aware of for positive that process
will not be given a brand new worth at some sudden 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 process = NetworkTask(
urlsessionTask: urlSessionTask
)
add(fromTask: urlSessionTask, metaData: metaData, completion: { [task] end in
Activity {
await process.sendResult(end result.mapError({ $0 as any Error }))
}
})
Altenatively, you can make an express fixed seize earlier than your Activity
runs:
var process = NetworkTask(
urlsessionTask: urlSessionTask
)
let theTask = process
add(fromTask: urlSessionTask, metaData: metaData, completion: { end in
Activity {
await theTask.sendResult(end result)
}
})
This isn’t as elegant however could be wanted in instances the place you do need to cross your variable to a bit 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 instantly within the process if there is not any additional wrapping closures concerned).
Whenever 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 instances it signifies that it’s worthwhile to both change your var
to a let
or that it’s worthwhile to carry out an express seize of your variable both by making a shadowing let
or by way of a seize checklist on the primary concurrent little bit of code that accesses your variable. Within the case of the instance on this publish that is the completion
closure however for you it could be instantly on the Activity
.