Swift 闭包捕获不是通过 for 循环中的引用?

标签 swift closures

如果我像这样写一个 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
-----

zipblockmultblock 闭包配对,每个循环在一对上运行。

multblock 闭包对捕获的变量进行变异,输出清楚地表明已经捕获了 5 个不同的变量,并且表明变量是作为引用(而不是按值)捕获的) 因为 blockmultblock 闭包对显然正在访问 i 的相同值。

在您的第二个示例中,所有闭包都捕获相同的单个 i 变量,并且它们都在该变量递增到 5 后运行。

关于Swift 闭包捕获不是通过 for 循环中的引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57690501/

相关文章:

swift - 从闭包中抛出错误

swift - 无法使用类型 'Range<String.Index>' 的参数列表调用类型 '(Range<String.Index>)' 的初始值设定项

JavaScript 关闭问题 : why is the second call to outerFn creating a new instance of outerVar?

swift - 包装/展开术语 (Swift)

ios - CLLocation 距离跟踪开始时不正确

javascript - 为什么这个闭包不能访问 'this' 关键字? -jQuery

循环内的 JavaScript 闭包 – 简单的实际示例

Haskell IORef - 一个答案与一个获得答案的函数

ios - 读取自定义对象的数据以填充 TableView

swift - NSKeyedArchiver 和 NSKeyedUnarchiver 取决于 Bundli-ID