Почему возможен сильный ссылочный цикл с NSNotificationCenter, но не с UIView.animateWithDuration?

С блоком NSNotificationCenter я должен использовать [unowned self], чтобы избежать сильного ссылочного цикла:

NSNotificationCenter.defaultCenter()
    .addObserverForName(UIApplicationWillEnterForegroundNotification,
        object: nil,
        queue: nil,
        usingBlock: { [unowned self] (notification : NSNotification!) -> Void in
            self.add(123)
        })

Однако в UIView.animateWithDuration мне не нужно использовать [unowned self]:

   UIView.animateWithDuration(0.5, animations: { () -> Void in
      self.someOutlet.alpha = 1.0
      self.someMethod()
   })

Какая разница?

2 ответа

Решение

Единственное различие между блоком анимации и центральным блоком уведомлений заключается в том, что блок анимации является чрезвычайно коротким - он выполняется немедленно, а затем освобождается.

В обоих случаях блоки будут захватывать self; но только NSNotificationCenter Код проблематичен, потому что центр уведомлений будет хранить ссылку на блок бесконечно, так как уведомление может происходить в любое время.

Обратите внимание, что это отличается от круговой ссылки. Циклическая ссылка часто создается объектом, содержащим ссылку на блок, который захватывает себя, например:

self.myBlock = {
   self.doSomething()
}

Эта круговая ссылка означает, что self никогда не будет освобожден. Центр уведомлений не является циклической ссылкой (поскольку self не содержит ссылку на центр уведомлений), это просто обычная ссылка, которая будет храниться до удаления наблюдателя.

animations: () -> Void а также completion: ((Bool) -> Void)? блоки для анимации UIView не сохраняют ссылку на себя. Этот предыдущий пост очень информативен по теме

Нужно ли использовать __weak self внутри UIAnimationBlocks в ARC?


Блок уведомлений (NSNotification) -> Void сохраняет ссылку на себя, передавая ее как неизвестную в вашем случае, она не должна увеличивать счет сохранения. Я пытаюсь убедиться, что я использую либо непризнанный, либо слабый, в любой ссылке, которую я передаю в закрытие. Здесь есть отличный пост об этом http://krakendev.io/blog/weak-and-unowned-references-in-swift


Но я настоятельно рекомендую держаться подальше от использования уведомлений, особенно с блоками, поскольку, возможно, в этой статье указана ошибка, которая была шокирующей, когда я ее прочитал.

http://sealedabstract.com/code/nsnotificationcenter-with-blocks-considered-harmful/

Другие вопросы по тегам