Все записи в списке захвата создают локальную переменную в закрытии . Он инициализируется значением переменной с тем же именем во внешнем контексте, но может быть изменен независимо от .
В вашем случае
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
Для получения дополнительной информации и получения дополнительной информации см "Capture Lists" в Swift ссылок (спасибо так @Arthur для обеспечения ссылки).
Возможный дубликат [Как блокировки фиксируют значения из предыдущих вызовов?] (Http://stackoverflow.com/questions/37839020/how-do-closures-capture-values-from-previous-calls) – Honey
@Honey: Я не уверен, что это дубликат. Это связано, но в этом вопросе нет списков захвата, и нет классов (ссылочных типов). –
@MartinR Ohhhhk – Honey