Why do I need to remove a notification observer before the object I'm observing is deallocated? - cocoa-touch

From https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/Reference/Reference.html:
You must invoke removeObserver: or removeObserver:name:object: before any object specified by
addObserverForName:object:queue:usingBlock: is deallocated
Why does it matter that I stop observing before the object whose notifications I'm observing is deallocated? I understand why I as the observer need to stop observing if I'm going to disappear and the block depends on my existence, but I don't understand why the lifetime of the observed object matters. Am I misinterpreting this?

I understand why I as the observer need to stop observing if I'm going to disappear and the block depends on my existence, but I don't understand why the lifetime of the observed object matters.
I think that a possible explanation is the following.
addObserverForName:object:queue:usingBlock description says:
Adds an entry to the receiver’s dispatch table with a notification queue and a block to add to the queue, and optional criteria: notification name and sender.
"sender" in this context is just another name for the object parameter, which is described in the following terms:
The object whose notifications you want to add the block to the operation queue.
If you pass nil, the notification center doesn’t use a notification’s sender to decide whether to add the block to the operation queue.
So, object acts as a sort of filter: when a notification comes in, the notification center decides based on that value (if present) if the block must be added to the specified operation queue.
Now, consider this:
the observed object is deallocated without the observer to be removed;
a different object, also able to post notifications is created, and it happens it has the same address as the object deallocated at point 1;
now the observer will react to notifications posted by the second object.
I admit it is a pretty rare case, but it might happen, so you better code against it.

If u don't remove observer, it may leed to a situation when you already destroyed an object but it is still sent notifications - this will cause "message sent to deallocated instance" error

Related

Many observer connected to one observable receive events one at a time

This is how I create my observable:
Observable.fromCallable(new EventObtainer()).flatMap(Observable::from).subscribeOn(Schedulers.io()).repeat();
And after that, through http request i'm trying to add different observers. The thing is that if I have more than one observer I can't predict which observer will obtain emitted item. Why doesn't observable emit item to every subscribed observer, but one item at time to different observers?
I resolved this,
In observable contract:
http://reactivex.io/documentation/contract.html
There is information:
There is no general guarantee that two observers of the same
Observable will see the same sequence of items.
So i resolved it by making my observable Connectable observable by publish, and then invoke connect method on it:
Observable.fromCallable(new EventObtainer()).flatMap(Observable::from).subscribeOn(Schedulers.io()).repeat().publish();
observable.connect();
and now even if asynchronously i will add more observers it will emit obtained item to every observers.

Refresh private queue when main queue changes in Core Data

I have two managed object contexts in my application, one of type NSMainQueueConcurrencyType, the other a temporary NSPrivateQueueConcurrencyType for background work.
I couldn't find the official solution to the following situation: When the private queue is doing some background work while the main queue deletes an object, I get an uncaught exception "Core Data could not fulfill a fault" when accessing this object in the background queue since it was deleted.
This is an expected behavior, however I am wondering how to handle these cases without getting a fault exception. I'm thinking this can be fixed by listening to the "NSManagedObjectContextDidSaveNotification" notification and then merging the background context with the main context but is this really the best way to do?
Yes, observe the did-save notification, and merge the changes with
[context mergeChangesFromContextDidSaveNotification:notification];
Also, you want to make sure you have setup an appropriate merge policy.

The Receptionist Design Pattern (How to redirect to main thread?)

The Receptionist Pattern is a design pattern that provides a way to redirect an event from one thread to another thread for it to be processed. The magic of using Key-Value Observing (KVO). More info: Receptionist
I understand the concept and the code. What I am struggling with is understanding how to accomplish the following:
"One common situation where the Receptionist pattern is useful is
key-value observing. In key-value observing, changes to the value of
an model object’s property are communicated to observers via KVO
notifications. However, changes to a model object can occur on a
background thread. This results in a thread mismatch, because changes
to a model object’s state typically result in updates to the user
interface, and these must occur on the main thread. In this case, you
want to redirect the KVO notifications to the main thread. where the
updates to an application’s user interface can occur."
Here is a snippet of what is described in the sample implementation.
The client object supplies the block code that updates the user
interface when it creates a receptionist object, as shown in Listing
4-4. Note that when it creates the receptionist object, the client
passes in the operation queue on which the block is to be executed, in
this case the main operation queue.
RCReceptionist *receptionist = [RCReceptionist receptionistForKeyPath:#"value" object:model queue:mainQueue task:^(NSString *keyPath, id object, NSDictionary *change) {
NSView *viewForModel = [modelToViewMap objectForKey:model];
NSColor *newColor = [change objectForKey:NSKeyValueChangeNewKey];
[[[viewForModel subviews] objectAtIndex:0] setFillColor:newColor];
}];
Simply asked, how does one acquire the main operation queue (aka 'mainQueue') off the main thread? Can someone help me connect the dots here please.
To grab the main operation queue:
[NSOperationQueue mainQueue];

Matching CoreData save notifications for callbacks

I'd like to pick someone's brain on this. I have a dedicated save NSManagedObjectContext and GCD queue from which I operate on it. And whenever new data comes into my app I save it on that context and merge the changes into the main context. My problem arises in telling the main thread what just happened. Right after I call save my current context is now up-to-date, but if I fire a method in the main context it's context isn't. If I wait for the NSManagedObjectContextDidSave notification, and I save three times, I now have three queued delegate calls but no way to match them to the notifications coming in. Does anyone know of a good way to get around this?
EDIT
What I ended up doing was creating a new context for each save operation and attaching a block to be called when the save notification arrived. It looks like this, http://pastie.org/2068084
From your answer to my comment above, I see that you pass along the managedObjectContext in the notification. I'm not that confident about asynchronous stuff yet, but I do think that you're violating some concurrency rule, if I correctly interpret this quote from the NSManagedObjectContext Class Reference:
Concurrency
Core Data uses thread (or serialized queue) confinement to protect managed objects and managed object contexts (see “Concurrency with Core Data”). A consequence of this is that a context assumes the default owner is the thread or queue that allocated it—this is determined by the thread that calls its init method. You should not, therefore, initialize a context on one thread then pass it to a different thread. Instead, you should pass a reference to a persistent store coordinator and have the receiving thread/queue create a new context derived from that.
I'd say, try passing along the persistent store coordinator in the notification and recreate the managed object context in the block.
I'm not sure what you mean by, " ...if I fire a method in the main context it's context isn't. If I wait for the NSManagedObjectContextDidSave..." That implies that you are not waiting until the contexts have been merged. If so, that is why you can't access the data, it's just not in the front context.
Do you call mergeChangesFromContextDidSaveNotification: from the front context after it receives the notification?

how to find objects with autorelease message?

My application crashes when the autorelease pool is released. The reason seems to be that the object with autorelease message is sent a release message sometime before the pool is released, hence the application crashes for object which is already released.
Hence I want to find which objects have a pending autorelease message, so that I can balance the retain .. release/autorelease messages to that object
if you dont know about 'NSZombieEnabled' you definitely need to check it out - Instructions are here
It won't tell you which objects are in the autoreleasepool but it will tell you which objects are being over-released.
In brief:
1)Double-click an executable in the Executables group of your Xcode project.
2)Click the Arguments tab.
3)In the "Variables to be set in the environment:" section, make a variable called "NSZombieEnabled" and set its value to "YES".