如果我像这样写一个 block 示例
var i = 0
var allBlocks :[()->()] = []
for i in 1...5 {
var block:() -> () = {print(i)}
allBlocks.append(block)
}
for var block2:() -> () in allBlocks {
block2()
}
输出将是
1
2
3
4
5
但是如果我这样写
var i = 0
var allBlocks :[()->()] = []
for _ in 1...5 {
var block:() -> () = {print(i)}
allBlocks.append(block)
i += 1
}
for var block2:() -> () in allBlocks {
block2()
}
输出将是
5
5
5
5
5
似乎第二个示例 block 捕获 i 作为引用,而在第一个示例中 i 是按值捕获的?这些例子的区别背后的原因是什么?
最佳答案
这两个示例都在捕获对名为 i
的变量的引用。在您的第一个示例中,i
是循环变量,实际上有 5 个单独的变量,每个变量都名为 i
。每个循环都有自己的名为 i
的变量。
考虑这个扩展示例,我们在循环中捕获每个变量两次:
var allBlocks: [()->()] = []
var multBlocks: [()->()] = []
for var i in 1...5 {
let block = { print(i) }
let multblock = { i *= 10 }
allBlocks.append(block)
multBlocks.append(multblock)
}
for (block, multblock) in zip(allBlocks, multBlocks) {
block()
multblock()
block()
print("-----")
}
输出
1 10 ----- 2 20 ----- 3 30 ----- 4 40 ----- 5 50 -----
zip
将 block
和 multblock
闭包配对,每个循环在一对上运行。
multblock
闭包对捕获的变量进行变异,输出清楚地表明已经捕获了 5 个不同的变量,并且表明变量是作为引用(而不是按值)捕获的) 因为 block
和 multblock
闭包对显然正在访问 i
的相同值。
在您的第二个示例中,所有闭包都捕获相同的单个 i
变量,并且它们都在该变量递增到 5
后运行。
关于Swift 闭包捕获不是通过 for 循环中的引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57690501/