I am trying to use dispatch queues in swift, but some weired beheviour appeared when calling the async function. In the following code I called the function "fun" 10 times each time with the .async function, and as I know from other languages that it will push the function call with it parameters to the queue to be executed at some time, but the output was most of the time printing 10 on all calls, meaning that the value parameter that was given to the function was took when the function start executing, so it took its final value, which is not logical for me.
import Foundation
let queue = DispatchQueue(label: "swiftlee.concurrent.queue", attributes: .concurrent)
let lock = NSLock()
func fun(_ idx: Int) {
print(idx)
}
func calc() {
var index = 0
let dispatchGroup = DispatchGroup()
while index < 10{
dispatchGroup.enter()
queue.async {
fun(index)
dispatchGroup.leave()
}
index += 1
}
dispatchGroup.wait()
}
calc()
If I change the function parameter to an assigned local variable in the loop as in the next code it works fine and prints all the numbers from 0 to 9, but if we want to apply the same logic as the previous one, when the function executes how did it find the value of the variable x, while it was gone on the next iterations.
import Foundation
let queue = DispatchQueue(label: "swiftlee.concurrent.queue", attributes: .concurrent)
let lock = NSLock()
func fun(_ idx: Int) {
print(idx)
}
func calc() {
var index = 0
let dispatchGroup = DispatchGroup()
while index < 10{
dispatchGroup.enter()
let x = index
queue.async {
fun(x)
dispatchGroup.leave()
}
index += 1
}
dispatchGroup.wait()
}
calc()
This is not strange or weired, but intended. A closure is capturing its surrounding variables by reference, even if they are value types. What happens is:
queue.async
index
variable.index
value is outputtedIf you do not want this behaviour, you could either
index
value to a local variable outside the closure and use that orqueue.async {
[index] in
fun(index)
dispatchGroup.leave()
}
See e.g. https://www.marcosantadev.com/capturing-values-swift-closures/