【问题标题】:How swift closure captures Int?快速关闭如何捕获 Int?
【发布时间】:2019-11-12 06:23:16
【问题描述】:

想知道快速关闭捕获是如何工作的?就像i 值被捕获一样,认为j 值也会被捕获,但事实并非如此。有人能解释一下这个ij 是如何被快速关闭捕获的吗?

var statements = [()->()]()

var j = 10
for i in 1...10 {
    statements.append {
        print(i)
        print(j)
    }
}

statements[2]() //prints 3 and 10

j = 20

statements[5]() //prints 6 and 20, I was expecting 6 and 10

【问题讨论】:

    标签: swift closures


    【解决方案1】:

    有问题的闭包正在捕获对变量j 的引用,它将使用分配给j 的任何新值。如果您不想使用更新后的值,则必须使用以下语法,其中闭包将捕获值(变量 j 的副本)而不是引用,并且它不会改变。

    var j = 10
    for i in 1...10 {
        statements.append { [j] in
            print(i)
            print(j)
        }
    }
    

    关于变量ij 范围的评论示例。

    如果我们将i作为变量并在调用闭包之前更改值,它将更改其捕获的值,因为闭包已经捕获了变量i的引用,如下所示,

    var j = 10
    for var i in 1...10 {
        statements.append { [j] in
            print(i)
            print(j)
        }
        if i == 1 {
            i = 9999
            statements[0]()
        }
    }
    

    输出

    9999
    10
    

    但是,如果我们如下捕获ij 的值,那么一旦捕获这些值,闭包内部就不会发生任何变化。

    var j = 10
    for var i in 1...10 {
        statements.append { [i, j] in
            print(i)
            print(j)
        }
        if i == 1 {
            i = 9999
            statements[0]()
        }
    }
    

    输出

    1
    10
    

    【讨论】:

    • i 与我的问题中的j 有何不同?我检查了i 的地址,在循环的每次迭代中似乎都是相同的地址。那么,为什么 i 具有价值,而 j 具有参考价值?
    • 你也可以分享一些解释[j] in用法的链接吗?
    • @Saran,i 的范围仅限于循环的每次迭代,因此相同的内存可用于下一次迭代,并且将分配新值,因此每次迭代捕获的值都不同。而j 具有全局范围,并且闭包将根据使用情况进行操作。
    • 您可以查看本文档中的Capturing Values 部分以了解有关范围的一些详细信息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多