我有一个例子:

class Animal {
    var stamina = 0

    func increaseStamina() {
        stamina += 1
    }
}

var a = Animal()

var closure = { [weak a] in
    a?.stamina = 10
}

a.stamina // 0
a.increaseStamina()
a.stamina // 1
closure()
a.stamina // 10

如果我这样更改closure:
var closure = { [weak a] in
    a = Animal()
    a?.stamina = 10
}

然后它会打印出这样的内容:
a.stamina // 0
a.increaseStamina()
a.stamina // 1
closure()
a.stamina // 1

为什么最后一行不同?

最佳答案

捕获列表中的所有条目都会在
关闭。用变量的值初始化
在外部上下文中具有相同的名称,但可以修改
独立地。

在你的情况下

var closure = { [weak a] in
    a = Animal()
    a?.stamina = 10
}

闭包内部的a使用对之前创建的Animal对象的弱引用进行初始化,但它与外部a变量无关。 a = Animal()创建一个新实例并分配
对该局部变量a的引用。因为这是一个较弱的引用,
该对象将立即释放(您可以验证是否
通过在闭包中添加print(a)来实现)。外部变量a仍然引用原始对象:
print(a.stamina) // 0
a.increaseStamina()
print(a.stamina) // 1
print(ObjectIdentifier(a)) // ObjectIdentifier(0x0000000100a03060)
closure()
print(ObjectIdentifier(a)) // ObjectIdentifier(0x0000000100a03060)
print(a.stamina) // 1

如果省略捕获列表,则在闭包内添加a在闭包之外引用相同的变量,
并可以在闭包内部分配一个新实例:
var a = Animal()

var closure = {
    a = Animal()
    a.stamina = 10
}

print(a.stamina) // 0
a.increaseStamina()
print(a.stamina) // 1
print(ObjectIdentifier(a)) // ObjectIdentifier(0x0000000100b06ac0)
closure()
print(ObjectIdentifier(a)) // ObjectIdentifier(0x0000000100e00070)
print(a.stamina) // 10

有关更多信息和详细信息,请参见Swift引用资料中的"Capture Lists"(感谢@Arthur提供的
链接)。

关于ios - 在Swift中捕获列表,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39465726/

10-11 14:50