Where is the official mention about observer retain/release of NSNotificationCenter method? - objective-c

NSNotificationCenter is known not to retain/release the observers. It makes sense, and I also have experienced related issue.
Anyway today I realized that I really am not sure on this. The official documentation doesn't say anything about ref-counting stuffs.
Though its discussion section says that we have to unregister the observer before it deallocates, but it doesn't mean the center will not retain them. And deallocation timing can become different by the behavior of the center.
Then, I couldn't find anything from the documentation.
But in practice, we already know the add/remove observer method doesn't retain the observer by experience. Unretained reference is very exceptional behavior which may cause serious bug, then I believe that there should be an explicit mention on this.
Where is it?

No, observers are not retained. That's why when you make an object an observer, you must make sure that it stops observing in its dealloc method. Logically, an observed object should know nothing about the observer, shouldn't care about observers, and therefore shouldn't hold a strong reference to observers.

Related

Do observers need to be removed in Swift 4/Objective-C?

I'm trying to implement KVC/KVO in Swift 4. Much of the documentation I've read up on for KVC/KVO in Objective-C states that the observer needs to be removed when you are done with it. But, after looking at Apple's documentation of the implementation of KVO using Swift 4, they don't explicitly state whether or not the observer needs to be removed in a deinit method. They do not include a deinit method in the example class definition. But, I do not want to make any assumptions since all the Objective-C documentation I've read states that the observer needs to be removed.
https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/AdoptingCocoaDesignPatterns.html#//apple_ref/doc/uid/TP40014216-CH7-ID12
I'm just not sure whether or not the observer needs to be removed through a deinit. Any help or point in the direction of a reference would be great, thanks.
If you are talking about NSKeyValueObservation: No they don't.
From the transcript of the WWDC 2017 Video "What is new in Foundation"
There is no need for a deinit where I throw away or tear down my observation because it's tied to the life cycle of that observation token. And so when the controller goes away, the observation token will go away.
The rules around deregistering observers was relaxed in 10.13, from the Foundation Release Notes (emphasis added):
Relaxed Key-Value Observing Unregistration Requirements
Prior to 10.13, KVO would throw an exception if any observers were still registered after an autonotifying object's -dealloc finished running. Additionally, if all observers were removed, but some were removed from another thread during dealloc, the exception would incorrectly still be thrown. This requirement has been relaxed in 10.13, subject to two conditions:
The object must be using KVO autonotifying, rather than manually calling -will and -didChangeValueForKey: (i.e. it should not return NO from +automaticallyNotifiesObserversForKey:)
The object must not override the (private) accessors for internal KVO state
If all of these are true, any remaining observers after -dealloc returns will be cleaned up by KVO; this is also somewhat more efficient than repeatedly calling -removeObserver methods.
HTH

In ARC do we need to send removeObserver: explicitly?

Do we have to send removeObserver: explicitly for objects that have been added as observers to an NSNotificationCenter before?
I am bit confused and unable to find the exact answer for this.
Please provide me in detail, about this including why we need to removeObserver explicitly, and why don't compiler put it implicitly in class/application?
Yes, you need to call removeObserver:, if you don't the observed class could call all deallocated instance of the observer.
From 10.11 observers are not required to un-register in their deallocation method.
NSNotificationCenter and NSDistributedNotificationCenter 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 stores the observer as a zeroing weak reference.
Alternatively, if the object cannot be stored weakly (because it has a
custom retain/release mechanism that would prevent the runtime from
being able to store the object weakly) the object is stored as a
non-weak zeroing reference. This means that observers are not required
to un-register in their deallocation method.[1]
Removing the observer is always a smart idea.
If you don't remove the observer, messages will still be sent, even if the object was deallocated. It might even be attached to another object, which would definitely lead to serious trouble.
You always need to remove observers for KVO as well as for Notifications.

Removing observers in post-ARC Cocoa

So far I have been removing observers (notifications or KVO) in the dealloc. Since dealloc is gone in ARC, what's the recommended way to do this?
-dealloc is not gone under ARC. The ivar-releasing and super-calling aspects are handled automatically, allowing you to omit it if that's all you were going to do, but you should still implement it for other things if it makes sense to do so.

Shorthand way of releasing all retained properties?

We all know an object's properties should be released through its dealloc method, but often for objects with many properties this can be pretty cumbersome. It's kind of a headache especially when adding or removing new properties to remember to go back to dealloc and add and remove release calls.
Is there any method of releasing all of an object's properties generically? I wasn't able to find anything while looking through the docs, but could this be done through reflection if it's not already implemented?
I guess another simple option might be to just place all the properties in an array or other container object and always just release the container. Any other options?
I saw one once (and even used it). It involves using the Objective-C Runtime to loop through the properties of a class, check which ones have either a retain or copy flag, and then set them to nil. Then, your -dealloc implementation can be reduced to something like [self cleanupProperties] or something.
The long story short, however, I've stopped using that because of really wacky problems that I can't explain. I don't know for sure that this is what caused it, but it just seems clever enough that it would have some sort of nasty, unforeseen side-effects.
So, in answer to your question: it's definitely possible, but I'd advise you don't. Use garbage collection if possible! :)
Unless you can turn on garbage collection you're pretty much down to two options. As you suggested you could stuff all the property references into a single NSDictionary (which you would release in -dealloc). Otherwise you're stuck with the way it's usually done.
You can see more about garbage collection in Objective-C 2.0 here.

In ObjC, how to describe balance between alloc/copy/retain and auto-/release, in terms of location

As is common knowledge, calls to alloc/copy/retain in Objective-C imply ownership and need to be balanced by a call to autorelease/release. How do you succinctly describe where this should happen? The word "succinct" is key. I can usually use intuition to guide me, but would like an explicit principle in case intuition fails and that can be use in discussions.
Properties simplify the matter (the rule is auto-/release happens in -dealloc and setters), but sometimes properties aren't a viable option (e.g. not everyone uses ObjC 2.0).
Sometimes the release should be in the same block. Other times the alloc/copy/retain happens in one method, which has a corresponding method where the release should occur (e.g. -init and -dealloc). It's this pairing of methods (where a method may be paired with itself) that seems to be key, but how can that be put into words? Also, what cases does the method-pairing notion miss? It doesn't seem to cover where you release properties, as setters are self-paired and -dealloc releases objects that aren't alloc/copy/retained in -init.
It feels like the object model is involved with my difficulty. There doesn't seem to be an element of the model that I can attach retain/release pairing to. Methods transform objects from valid state to valid state and send messages to other objects. The only natural pairings I see are object creation/destruction and method enter/exit.
Background:
This question was inspired by: "NSMutableDictionary does not get added into NSMutableArray". The asker of that question was releasing objects, but in such a way that might cause memory leaks. The alloc/copy/retain calls were generally balanced by releases, but in such a way that could cause memory leaks. The class was a delegate; some members were created in a delegate method (-parser:didStartElement:...) and released in -dealloc rather than in the corresponding (-parser:didEndElement:...) method. In this instance, properties seemed a good solution, but the question still remained of how to handle releasing when properties weren't involved.
Properties simplify the matter (the rule is auto-/release happens in -dealloc and setters), but sometimes properties aren't a viable option (e.g. not everyone uses ObjC 2.0).
This is a misunderstanding of the history of properties. While properties are new, accessors have always been a key part of ObjC. Properties just made it easier to write accessors. If you always use accessors, and you should, than most of these questions go away.
Before we had properties, we used Xcode's built-in accessor-writer (in the Script>Code menu), or with useful tools like Accessorizer to simplify the job (Accessorizer still simplifies property code). Or we just typed a lot of getters and setters by hand.
The question isn't where it should happen, it's when.
Release or autorelease an object if you have created it with +alloc, +new or -copy, or if you have sent it a -retain message.
Send -release when you don't care if the object continues to exist. Send -autorelease if you want to return it from the method you're in, but you don't care what happens to it after that.
I wouldn't say that dealloc is where you would call autorelease. And unless your object, whatever it may be, is linked to the life of a class, it doesn't necessarily need to be kept around for a retain in dealloc.
Here are my rules of thumb. You may do things in other ways.
I use release if the life of the
object I am using is limited to the
routine I am in now. Thus the object
gets created and released in that
routine. This is also the preferred
way if I am creating a lot of objects
in a routine, such as in a loop, and
I might want to release each object
before the next one is created in the
loop.
If the object I created in a method
needs to be passed back to the
caller, but I assume that the use of
the object will be transient and
limited to this run of the runloop, I
use autorelease. Here, I am trying to mimic many of Apple's convenience routines. (Want a quick string to use for a short period? Here you go, don't worry about owning it and it will get disposed appropriately.)
If I believe the object is to be kept
on a semi-permanent basis (like
longer than this run of the runloop),
I use create/new/copy in my method
name so the caller knows that they
are the owner of the object and will
have to release the object.
Any objects that are created by a
class and kept as a property with
retain (whether through the property
declaration or not), I release those
in dealloc (or in viewDidUnload as
appropriate).
Try not to let all this memory management overwhelm you. It is a lot easier than it sounds, and looking at a bunch of Apple's samples, and writing your own (and suffering bugs) will make you understand it better.