Thursday, September 11, 2025
HomeiOS DevelopmentFixing “Reference to captured var in concurrently-executing code” in Swift

Fixing “Reference to captured var in concurrently-executing code” in Swift


Revealed on: July 31, 2024

When you begin migrating to the Swift 6 language mode, you may almost certainly activate strict concurrency first. As soon as you have carried out this there will likely be a number of warings and errors that you’re going to encounter and these errors will be complicated at instances.

I will begin by saying that having a stable understanding of actors, sendable, and knowledge races is a big benefit if you wish to undertake the Swift 6 language mode. Just about all the warnings you may get in strict concurrency mode will inform you about potential points associated to operating code concurrently. For an in-depth understanding of actors, sendability and knowledge races I extremely advocate that you just check out my Swift Concurrency course which is able to get you entry to a collection of movies, workout routines, and my Sensible Swift Concurrency e book with a single buy.

WIth that out of the best way, let’s check out the next warning that you just would possibly encounter in your undertaking:

Reference to captured var in concurrently-executing code

This warning tells you that you just’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(
    urlsessionTask: urlSessionTask
)

add(fromTask: urlSessionTask, metaData: metaData, completion: { end in
    Process {
        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 that we will assign a distinct worth to that job at any time and that would end in inconsistencies in our knowledge. For instance, if we assign a brand new worth to the job earlier than the closure begins operating, we’d have captured the previous job which could possibly be surprising.

Since strict concurrency is supposed to assist us guarantee that our code runs as freed from surprises as potential, Swift desires us to guarantee that we seize a relentless worth as an alternative. On this case, I am not mutating job anyway so it is secure to make it a let:

let job = NetworkTask(
    urlsessionTask: urlSessionTask
)

add(fromTask: urlSessionTask, metaData: metaData, completion: { end in
    Process {
        await job.sendResult(outcome)
    }
})

This variation eliminates the warning as a result of the compiler now is aware of for positive that job will not be given a brand new worth at some surprising time.

One other strategy to repair this error can 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 won’t change unexpectedly.

var job = NetworkTask(
    urlsessionTask: urlSessionTask
)

add(fromTask: urlSessionTask, metaData: metaData, completion: { [task] end in
    Process {
        await job.sendResult(outcome.mapError({ $0 as any Error }))
    }
})

Altenatively, you could possibly make an specific fixed seize earlier than your Process runs:

var job = NetworkTask(
    urlsessionTask: urlSessionTask
)

let theTask = job
add(fromTask: urlSessionTask, metaData: metaData, completion: { end in
    Process {
        await theTask.sendResult(outcome)
    }
})

This isn’t as elegant however is likely to be wanted in instances the place you do wish to go 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 job if there is not any further wrapping closures concerned).

While you first encounter this warning it is likely to 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 essential to both change your var to a let or that it’s essential to carry out an specific 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 is likely to be straight on the Process.

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments