为什么 NSNotificationCenter 可以实现强引用循环而不是 UIView.animateWithDuration?
Why is a strong reference cycle possible with NSNotificationCenter but not 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()
})
有什么区别?
UIView 动画的 animations: () -> Void
和 completion: ((Bool) -> Void)?
块不保留对自身的引用。之前的 post 对主题
提供了很多信息
通知块 (NSNotification) -> Void
确实保留了对自身的引用,在您的情况下将其作为无主传递,它不应增加保留计数。我尽量确保我在传递给闭包的任何引用上使用 unowned 或 weak。在这里 http://krakendev.io/blog/weak-and-unowned-references-in-swift
找到了一个很棒的 post
但是,我强烈建议不要使用通知,尤其是块,因为这篇文章可能指出了一个错误,当我读到它时感到震惊。
http://sealedabstract.com/code/nsnotificationcenter-with-blocks-considered-harmful/
动画块和通知中心块的唯一区别是动画块的生命周期极短——立即执行然后释放。
在这两种情况下,块将捕获 self
;但只有 NSNotificationCenter
代码有问题,因为通知中心将无限期地持有对该块的引用,因为通知可能随时发生。
请注意,这与循环引用不同。循环引用通常由持有对捕获自身的块的引用的对象创建,如下所示:
self.myBlock = {
self.doSomething()
}
循环引用意味着 self
永远不会被释放。通知中心不是循环引用(因为 self 不持有对通知中心的引用),它只是一个常规引用,将一直保留到观察者被移除。
对于 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()
})
有什么区别?
UIView 动画的 animations: () -> Void
和 completion: ((Bool) -> Void)?
块不保留对自身的引用。之前的 post 对主题
通知块 (NSNotification) -> Void
确实保留了对自身的引用,在您的情况下将其作为无主传递,它不应增加保留计数。我尽量确保我在传递给闭包的任何引用上使用 unowned 或 weak。在这里 http://krakendev.io/blog/weak-and-unowned-references-in-swift
但是,我强烈建议不要使用通知,尤其是块,因为这篇文章可能指出了一个错误,当我读到它时感到震惊。
http://sealedabstract.com/code/nsnotificationcenter-with-blocks-considered-harmful/
动画块和通知中心块的唯一区别是动画块的生命周期极短——立即执行然后释放。
在这两种情况下,块将捕获 self
;但只有 NSNotificationCenter
代码有问题,因为通知中心将无限期地持有对该块的引用,因为通知可能随时发生。
请注意,这与循环引用不同。循环引用通常由持有对捕获自身的块的引用的对象创建,如下所示:
self.myBlock = {
self.doSomething()
}
循环引用意味着 self
永远不会被释放。通知中心不是循环引用(因为 self 不持有对通知中心的引用),它只是一个常规引用,将一直保留到观察者被移除。