在Swift中捕获列表

Khu*_*ong 9 ios swift

我有一个例子:

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
Run Code Online (Sandbox Code Playgroud)

如果我改变了closure这样的话:

var closure = { [weak a] in
    a = Animal()
    a?.stamina = 10
}
Run Code Online (Sandbox Code Playgroud)

然后它打印出这样的东西:

a.stamina // 0
a.increaseStamina()
a.stamina // 1
closure()
a.stamina // 1
Run Code Online (Sandbox Code Playgroud)

为什么最后一行不同?

Mar*_*n R 6

捕获列表中的所有条目都在闭包中创建一个局部变量.它使用外部上下文中具有相同名称的变量值进行初始化,但可以单独修改.

在你的情况下

var closure = { [weak a] in
    a = Animal()
    a?.stamina = 10
}
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

如果省略捕获列表,则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
Run Code Online (Sandbox Code Playgroud)

有关更多信息和详细信息,请参阅Swift参考中的"捕获列表"(感谢@Arthur提供链接).

  • 由于我也很好奇,[这里是Apple的Swift参考(Swift 2.2)中的相关部分](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Expressions.html#// apple_ref/doc/uid/TP40014097-CH32-ID544):"对于捕获列表中的每个条目,常量初始化为在周围范围内具有相同名称的常量或变量的*值*[...] " (2认同)