Is there a mechanism which would allow an object to know that a zeroing weak reference turned nil?
For example I have a property
@property (nonatomic, weak) MyClass *theObject;
when theObject deallocates and the property turns nil I want to get notified. But how? Does the zeroing weak reference system use the setter to set the property to nil when the object goes away?
The runtime just sets the weak ivar _theObect to nil, a custom setter is not called.
What you could do (if you really need the notification):
When _theObject is deallocated, the associated object is released and deallocated (if there are no other strong refereces to it). Therefore its dealloc method is called. This is your "notification".
(I'm writing this on the phone and can fill in the details later if necessary.)
I implemented this using a so-called weak reference registry, see the class BMWeakReferenceRegistry, part of my open source BMCommons framework for iOS.
This class associates context objects with the object of interest. When this object is released, so is the context object and the cleanup block is called.
See the API:
There is no notification about object deallocation.
The system will not use setter method (this means no KVO notifications will be raised). The ivar is the real weak reference which gets zeroed. The
weak
keyword on a property is merely an instruction for synthesizing the ivar, and a public declaration that the object is not retained.Though you can always invent your own notifications and send them from
dealloc
method of your classes, note that normally you should not ever be interested in such notifications and there is at least one good reason that they don't exist.Whenever there is any kind of automatic memory management is in use, you can not (by definition) expect objects to die exactly when you need them to, that applies to Objective-C reference counting. Because any component may unexpectedly prolong lifetime of any object for unknown period of time, relying program behavior on assumption that
dealloc
will be called exactly when you need it to is bad design and a recipe for trouble.dealloc
should be used for cleaning up only.Try this rule of thumb: will the program still work correctly if
dealloc
does not get called at all? If not, you should rethink program's logic rather than sending out dealloc notifications.The following is an example that I used to implement multicast of delegates. It might be useful to illustrate how to monitor the 'dealloc' of weak referenced objects (the delegates).
There will be a master DelegateRef object. Its array keeps record of all delegateRefs which wrap the real delegates. The main purpose here is to remove the strong reference to delegateRefs kept by the array when the real delegates dealloc. Therefore, a local watch object is created and associated to delegate when adding the delegate. When the local watch dealloc, the delegateRef gets removed from the master DelegateRef's array.
Based on Martin R's answer, I came up with the following snippet. Just make sure you don't create any retain cycles with your onDeinit closure!
Call it like this when initializing your weak var:
there is no notification system for weak vars.