Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NotificationCenter.default.removeObserver(self) in deinit, why deinit it even get called?

Starting with ios 9 it is not necessary to unsubscribe from notification center since ios handles this automatically, but prior to ios 9 developers had to manually call NotificationCenter.default.removeObserver(self) in order to avoid memory leaks and common place for this was(it is suggested in a lot of tutorials and Stackoverflow posts) deinit. So, my question is - how it was possible to use deinit to unregister from notifications since deinit is only called before objects deallocation, so its ref count should be 0, but for sure it is not - since we're still subscribe to the notification center. The only possible way to achieve this seems to be use of weak references, basically if notification center references object weakly the above mentioned scenario is possible, but in this case unsubscribing is not needed at all since the object can be easily deallocated. Can somebody clarify a bit on how this works.

like image 353
starwarrior8809 Avatar asked Mar 02 '23 17:03

starwarrior8809


1 Answers

I think that prior to iOS9 NotificationCenter was adding observers as unretained pointers. Thus the point of removing observers in dealloc was not to prevent retain cycle but to prevent a crash when notification to released object could be sent.

From the iOS9 the NotificationCenter started using zeroing-weak referencing so it became possible to skip removing observers. You could find more details in the release notes:

In OS X 10.11 and iOS 9.0 NSNotificationCenter and NSDistributedNotificationCenter will no longer send notifications to registered observers that may be deallocated. If the observer is able to be stored as a zeroing-weak reference the underlying storage will store the observer as a zeroing weak reference, alternatively if the object cannot be stored weakly (i.e. it has a custom retain/release mechanism that would prevent the runtime from being able to store the object weakly) it will store the object as a non-weak zeroing reference. This means that observers are not required to un-register in their deallocation method. The next notification that would be routed to that observer will detect the zeroed reference and automatically un-register the observer. If an object can be weakly referenced notifications will no longer be sent to the observer during deallocation; the previous behavior of receiving notifications during dealloc is still present in the case of non-weakly zeroing reference observers. Block based observers via the -[NSNotificationCenter addObserverForName:object:queue:usingBlock] method still need to be un-registered when no longer in use since the system still holds a strong reference to these observers. Removing observers (either weakly referenced or zeroing referenced) prematurely is still supported. CFNotificationCenterAddObserver does not conform to this behavior since the observer may not be an object.

like image 55
ScorpiCon Avatar answered Apr 07 '23 05:04

ScorpiCon