Rectangle 27 0

ios Objective C: Where to remove observer for NSNotification?


@IsaacOveracker a few reasons: your setup up code (eg. loadView and viewDidLoad) could potentially cause the notifications to be fired and your controller needs to reflect that before it shows. If you do it like this there are a few benefits. At the moment you decided to "leave" the controller you don't care about the notifications and they wont cause you to do logic while the controller is being pushed off screen etc. There are special cases where the controller should receive notifications when it is off-screen I guess you can't do this. But events like that should probably be in your model.

@IsaacOveracker also with ARC it would be weird to implement dealloc to unsubscribe to notifications.

I'm curious, @RickiG: why do you recommend using viewWillAppear and viewWillDisappear for viewControllers?

If the observer is added to a viewController I strongly recommend adding it in viewWillAppear: and removing it in the viewWillDissapear:

Of those what I've tried, with iOS7 this is the best way to register/remove observers when working with UIViewControllers. The only catch is that, in many cases you don't want the observer to be removed when using UINavigationController and pushing another UIViewController to the stack. Solution: You can check if the VC is being popped in viewWillDisappear by calling [self isBeingDismissed].

Popping the view controller from navigation controller may not cause dealloc to be called immediately. Going back into the view controller may then cause multiple notifications if observer is added in initialization commands.

Note
Rectangle 27 0

ios Objective C: Where to remove observer for NSNotification?


[[NSNotificationCenter defaultCenter] removeObserver:observerObjectHere];
- (void)viewWillDisappear:(BOOL)animated{
 if (![[self.navigationController viewControllers] containsObject: self]) //any other hierarchy compare if it contains self or not
    {
        // the view has been removed from the navigation stack or hierarchy, back is probably the cause
        // this will be slow with a large stack however.

        [[NSNotificationCenter defaultCenter] removeObserver:observerObjectHere];
    }
}
UIViewController
hierarchy
iOS 6.0
lesser
navigation stack
remove observer
removeObserver:self
removed
view
viewDidUnload

@Prince can you explain why viewWillDisapper better then dealloc? so we have add observer to self, so when the self will be dropped from memory it will call dealloc and then all observers will be deleted, is this not a good logic.

@wcochran automatically reload/refresh in viewWillAppear:

Except a controller may still want notifications when its view is not showing (e.g. to reload a tableView).

In iOS 6.0 , its better to remove observer in viewWillDisappear as viewDidUnload method is deprecated.

Putting the removeObserver calls in viewWillDisappear as indicated is definitely the right way to go if the controller is being presented via pushViewController. If you put them in dealloc instead then dealloc will never be called -- in my experience at least...

Note
Rectangle 27 0

ios Objective C: Where to remove observer for NSNotification?


If you've added the observer in viewDidLoad you should remove it in both dealloc and viewDidUnload. Otherwise you'll end up adding it twice when viewDidLoad is called after viewDidUnload (this will happen after a memory warning). This isn't necessary in iOS 6 where viewDidUnload is deprecated and won't be called (because views are no longer automatically unloaded).

Welcome to StackOverflow. Please checkout the MarkDown FAQ (question-mark icon next to the question/answer edit box). Using Markdwon will improve the usability of your answer.

Note
Rectangle 27 0

ios Objective C: Where to remove observer for NSNotification?


[[NSNotificationCenter defaultCenter] removeObserver:observerObjectHere];
- (void)viewWillDisappear:(BOOL)animated{
    if ([self isBeingDismissed] == YES) ///presented view controller
    {
        // remove observer here
        [[NSNotificationCenter defaultCenter] removeObserver:observerObjectHere];
    }
}
- (void)viewWillDisappear:(BOOL)animated{
 if (![[self.navigationController viewControllers] containsObject: self]) //any other hierarchy compare if it contains self or not
    {
        // the view has been removed from the navigation stack or hierarchy, back is probably the cause
        // this will be slow with a large stack however.

        [[NSNotificationCenter defaultCenter] removeObserver:observerObjectHere];
    }
}
UIViewController
override func viewWillDisappear(animated: Bool){
    super.viewWillDisappear(animated)

    if self.isBeingDismissed()  //presented view controller
    {
        // remove observer here
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }
}
removeObserver:self

There is many times its better to remove observer when the view has been removed from the navigation stack or hierarchy.

@Prince can you explain why viewWillDisapper better then dealloc? so we have add observer to self, so when the self will be dropped from memory it will call dealloc and then all observers will be deleted, is this not a good logic.

@wcochran automatically reload/refresh in viewWillAppear:

Except a controller may still want notifications when its view is not showing (e.g. to reload a tableView).

In iOS 6.0 > version , its better to remove observer in viewWillDisappear as viewDidUnload method is deprecated.

Putting the removeObserver calls in viewWillDisappear as indicated is definitely the right way to go if the controller is being presented via pushViewController. If you put them in dealloc instead then dealloc will never be called -- in my experience at least...

Note
Rectangle 27 0

ios Objective C: Where to remove observer for NSNotification?


@IsaacOveracker a few reasons: your setup up code (eg. loadView and viewDidLoad) could potentially cause the notifications to be fired and your controller needs to reflect that before it shows. If you do it like this there are a few benefits. At the moment you decided to "leave" the controller you don't care about the notifications and they wont cause you to do logic while the controller is being pushed off screen etc. There are special cases where the controller should receive notifications when it is off-screen I guess you can't do this. But events like that should probably be in your model.

@IsaacOveracker also with ARC it would be weird to implement dealloc to unsubscribe to notifications.

I'm curious, @RickiG: why do you recommend using viewWillAppear and viewWillDisappear for viewControllers?

If the observer is added to a view controller, I strongly recommend adding it in viewWillAppear and removing it in viewWillDisappear.

Of those what I've tried, with iOS7 this is the best way to register/remove observers when working with UIViewControllers. The only catch is that, in many cases you don't want the observer to be removed when using UINavigationController and pushing another UIViewController to the stack. Solution: You can check if the VC is being popped in viewWillDisappear by calling [self isBeingDismissed].

Popping the view controller from navigation controller may not cause dealloc to be called immediately. Going back into the view controller may then cause multiple notifications if observer is added in initialization commands.

Note
Rectangle 27 0

ios Objective C: Where to remove observer for NSNotification?


- (void)viewWillAppear:(BOOL)animated {
    NSLog(@"viewController will appear");
    // Add observers
    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"imageGenerated" object:nil]; // This is added to avoid duplicate notifications when the view is presented again
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receivedImageFromCameraOrPhotolibraryMethodOnListener:) name:@"actionCompleted" object:nil];

}
- (void)viewWillDisappear:(BOOL)animated {
    NSLog(@"viewController will disappear");
    if ([self isBeingDismissed]) {
        NSLog(@"viewController is being dismissed");
        [[NSNotificationCenter defaultCenter] removeObserver:self name:@"actionCompleted" object:nil];
    }
}

-(void)dealloc {
    NSLog(@"viewController is being deallocated");
    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"actionCompleted" object:nil];
}

As a solution I usually remove the observer in one of these two methods:

For similar reasons, when I issue the notification the first time, I need to account for the fact that any time a view with appear above the controller then viewWillAppear method is fired. This will in turn generate multiple copy of the same notification. Since there isn't a way to check if a notification is already active, I obviate the problem by removing the notification before adding it:

In this case, deallocating the notification in viewWillDisappear may be inconvenient if we are using the notification to allow the UIview to communicate with the parent view controller.

It is important to notice also that viewWillDisappear is called also when the view controller present a new UIView. This delegate simply indicate that the view controller main view is not visible on the display.

Note
Rectangle 27 0

ios Objective C: Where to remove observer for NSNotification?


-(void) dealloc {
      [[NSNotificationCenter defaultCenter] removeObserver:self];
      [super dealloc];
}

@pixelfreak stronger, it is not allowed under ARC to call [super dealloc]

Dirk is right -- this is incorrect. [super dealloc] must always be the last statement of your dealloc method. It destroys your object; after it runs, you don't have a valid self anymore. /cc @Dirk

I'd turn the order of these instructions around... Using self after [super dealloc] makes me nervous... (even if the receiver is unlikely to actually dereference the pointer in any way, well, you never know, how they implemented NSNotificationCenter)

If using ARC on iOS 5+, I think [super dealloc] is not needed anymore

Note
Rectangle 27 0

ios Objective C: Where to remove observer for NSNotification?


  • The implementation of the observer (When is it ready to receive notifications? When is it no longer ready?)
  • The intended life-time of the observer (Is it tied to some other object, say, a view or view controller?)

@MobileMon "For example, viewWillDisappear" The problem with giving a concrete advise is, that it really depends on what kind of object you register as observer for what kind of event. It may be the right solution to unregister an observer in viewWillDisappear (or viewDidUnload) for UIViewControllers, but that really depends on the use case.

@MobileMon -- yes. I hope, that that's the point I am getting across with my answer. Removing the observer in dealloc is only a last line of defence against crashing the app due to a later access to a decallocated object. But the proper place to unregister an observer is usually somewhere else (and often, much earlier in the object's life-cycle). I am not trying to say here "Hey, just do it in dealloc and everything will be fine".

Edit (since the answer seems to draw more comments than I would have thought) All I am trying to say here is: it's really hard to give general advice as to when it's best to remove the observer from the notification center, because that depends:

I suppose it should be noted in that one should remove observer somewhere else other than dealloc. For example, viewwilldisappear

I'd recommend, that you add a call [notificationCenter removeObserver: self] in method dealloc of those classes, which you intend to use as observers, as it is the last chance to unregister an observer cleanly. This will, however, only protect you against crashes due to the notification center notifying dead objects. It cannot protect your code against receiving notifications, when your objects are not yet/no longer in a state in which they can properly handle the notification. For this... See above.

So, the best general advice I can come up with: to protect your app. against at least one possible failure, do the removeObserver: dance in dealloc, since that's the last point (in the object's life), where you can do that cleanly. What this does not mean is: "just defer the removal until dealloc is called, and everything will be fine". Instead, remove the observer as soon as the object is no longer ready (or required) to receive notifications. That is the exact right moment. Unfortunately, not knowing the answers to any of the questions mentioned above, I cannot even guess, when that moment would be.

The generic answer would be "as soon as you no longer need the notifications". This is obviously not a satisfying answer.

You can always safely removeObserver: an object multiple times (and all but the very first call with a given observer will be nops). So: think about doing it (again) in dealloc just to be sure, but first and foremost: do it at the appropriate moment (which is determined by your use case).

Note
Rectangle 27 0

ios Objective C: Where to remove observer for NSNotification?


In OS X 10.11 and iOS 9.0 NSNotificationCenter and NSDistributedNotificationCenter will no longer send notifications to registered observers that may be deallocated.

May be they will not send messages to observers, but I believe they will keep a strong reference to them as I understand. In that case all observers will stay in memory and produce a leak. orrect me if I am wrong.

The linked documentation goes into detail about that. TL;DR: it's a weak reference.

Note
Rectangle 27 0

ios Objective C: Where to remove observer for NSNotification?


In general I put it into the dealloc method.

Note