Thursday, August 1, 2024
HomeiOS DevelopmentFixing “Reference to captured var in concurrently-executing code” in Swift

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


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.



Supply hyperlink

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments