Рассмотрим следующий фрагмент кода:
class myDropBounceAndRollBehavior: UIDynamicBehavior {
let v = UIView()
init(view v: UIView) {
self.v = v
super.init()
}
override func willMove(to anim: UIDynamicAnimator?) {
guard let anim = anim else {return}
let sup = self.v.superview!
let grav = UIGravityBehavior()
grav.action = { [unowned self] in
let items = anim.items(in: sup.bounds) as! [UIView]
if items.index(of: self.v) == nil {
anim.removeBehavior(self)
self.v.removeFromSuperview()
}
}
self.addChildBehavior(grav)
grav.addItem(self.v)
}
}
Здесь у нас есть класс с функцией willMove(anim:)
, которая имеет замыкание, которое ссылается на себя, создавая цикл сохранения.Чтобы решить эту проблему, Мэтт устанавливает self
в unowned self
, чтобы разорвать цикл.
Его следующий параграф говорит следующее:
Существует потенциальный (и довольно сложный) цикл сохраненияздесь: self.addChildBehavior(grav)
вызывает постоянную ссылку на grav
, grav
имеет постоянную ссылку на grav.action
, а анонимная функция, назначенная на grav.action
, ссылается на self
.Чтобы разорвать цикл, я объявил ссылку на self
как unowned
в списке захвата анонимной функции
С этим отрывком из книги я составил график ссылок для ситуации ниже
![enter image description here](https://i.stack.imgur.com/EeP7R.png)
Таким образом, при запуске функции willMove(anim:)
будет вызван вызов функции self.addChildBehavior(grav)
, который ссылается на grav
, создав сильную ссылкук справочному экземпляру grav
.но поскольку функция willMove(anim:)
живет в основном потоке, функция self.addChildBehavior(grav)
должна завершить до освобождения памяти кучи для willMove(anim:)
, поэтому self.addChildBehavior(grav)
больше не имеет строгой ссылки на grav
и willMove(anim:)
может завершиться и память освобождается из кучи.Результат будет выглядеть следующим образом:
![enter image description here](https://i.stack.imgur.com/3wTcP.png)
В этот момент, когда willMove(anim:)
завершит выполнение, единственные оставшиеся ссылки - это unowned self
ссылкак экземпляру и некоторой ссылке (например, let behavior = MyDropBounceAndRollBehaviour()
), а затем, когда анонимная функция завершит выполнение, будет только behaviour
ссылка на <MyDropAndBounceBehavior>
Имею ли я правильное понимание?