NSNotification stops updating on any of user interface events? - ios

I am using NSNotificationCenter to subscribe to event,
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(useNotificationWithLocation:)
name:#"somename"
object:nil];
And sending from static library,
[[NSNotificationCenter defaultCenter] postNotificationName:#"somename" object:nil userInfo:dictionary];
Everything works as expected, but when I use any of the UI event, like button click, I stop getting notification. I do not have any clue what is happening.
useNotificationWithLocation code,
-(void)useNotificationWithLocation:(NSNotification*)value
{
NSDictionary* dictionary = value.userInfo;
CLLocation *currentLoc = [dictionary valueForKey:CURRENT_LOCATION_NOTIFY];
NSLog(#"useNotificationWithLocation %#",currentLoc);
}
Please suggest what should I do about this.

Related

NSNotification argument in NSNotificationCenter method is nil

I have this really unexplained problem with NSNotification method.
I have been using NSNotificationCenter for a long time but i can't explain why this is happening.
My problem is this,
I have a UITableViewCell subclass where i send a NSNotificationCenter method to the UIViewController when a user taps a button in the cell.
[[NSNotificationCenter defaultCenter] postNotificationName:MOVE_TO_PROGRAM_VIEW
object:self
userInfo:#{INDEX_ROW : [NSNumber numberWithInteger:self.tag]}];
Where the self.tag is the row (for the data model in the controller).
In the controller i register for the notification in viewWillAppear: like so:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(userWantsToGoToProgramView:) name:MOVE_TO_PROGRAM_VIEW object:nil];
I also remove myself in the viewWillDisappear:
[[NSNotificationCenter defaultCenter] removeObserver:self name:MOVE_TO_PROGRAM_VIEW object:nil];
Now in the method for the notification i try to get the userInfo and the row but the notificaiton argument is nil for some reason..
- (void)userWantsToGoToProgramView:(NSNotification *)notification
{
// notification is nil here
// get the index of the video in the feed
NSDictionary *userInfo = notification.userInfo;
NSInteger videoIndex = [userInfo[INDEX_ROW] integerValue];
NSDictionary *videoData = self.feed[videoIndex];
}
Any advice of help will be appreciated
Thanks!

NSNotificationCenter calling two times

Below is what I have.
MainViewController.m
- (IBAction)sideMenuAction:(id)sender {
NSLog(#"login==sideMenuAction");
[[NSNotificationCenter defaultCenter] postNotificationName:#"ShowMySideMenuNotification" object:self];
}
NotificationListener.m
-(void)viewDidLoad {
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"ShowMySideMenuNotification" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(adjustShowMenu) name:#"ShowMySideMenuNotification" object:nil];
}
-(void) adjustShowMenu {
NSLog(#"notification adjustShowMenu=");
}
Now when I click side menu button in MainViewController, what I was expecting is call adjustShowMenu from NotificationListener once, however it is called twice.
Below is the NSLog for the same.
2015-01-20 12:27:30.798 abc[699:169314] login==sideMenuAction
2015-01-20 12:27:30.798 abc[699:169314] notification adjustShowMenu=
2015-01-20 12:27:30.799 abc[699:169314] notification adjustShowMenu=
What I was expecting is
2015-01-20 12:27:30.798 abc[699:169314] login==sideMenuAction
2015-01-20 12:27:30.798 abc[699:169314] notification adjustShowMenu=
Any idea what is going wrong?
Note: I also tried in viewDidAppear instead of viewDidLoad, but its giving same result.
When I searched online, many answers asked to removeObserver. I did same, but still twice notification is getting called.
As per answer here, I make changes as below and its working fine now.
-(void) viewWillAppear:(BOOL)animated {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(adjustShowMenu) name:#"ShowMySideMenuNotification" object:nil];
}
-(void) viewWillDisappear:(BOOL)animated {
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"ShowMySideMenuNotification" object:nil];
}

iOs Remove Observers from ViewController on TabBarController

I have a UITabBarController with some tab and in all of them i have:
-(void)viewDidappear:(BOOL)animated{
......
[[NSNotificationCenter defaultCenter] addObserverForName:kNotificationName object:nil queue: nil, usingBlock{...}
}
and
-(void)viewDidDisappear:(BOOL)animated{
......
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
In another class i post the notification with name kNotificationName:
[[NSNotificationCenter defaultCenter] postNotification:kNotificationName object:nil];
I've set some log on all of this methods, and the order they are called is correct but...if i switch from First to Second tab (and the notification is posted), the first and the second tab receive the notification (but the viewDidDisappear of the first tab is called!).
If from second tab i go to third tab, the first, second, and third tab receive the notification.
I've tried to use:
[[NSNotificationCenter defaultCenter] removeObserver:self name:postNotification:kNotificationName object:nil];
but the behaviour is the same. All observer are notified.
EDIT1:
As suggest to the other topic i've moved all in viewWillAppear: and viewWillDisappear:, but this haven't have any effect.
I've tried to remove the observer after have received the notification, like this:
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserverForName:kDLSyncEngineSyncCompletedNotificationName object:nil queue:nil usingBlock:^(NSNotification *note) {
....
[[NSNotificationCenter defaultCenter] removeObserver:self name:kDLSyncEngineSyncCompletedNotificationName object:nil];
}];
}
But, using this (bad) approach too, the notification is received to the first tab too (i've added this code only on the first tab, to check if after press the second tab, the first tab is receiving again the notification).
EDIT2 - SOLVED - (but what is the difference?)
Instead of using *addObserverForName:object:queue:usingBlock*: I've used *addObserver:selector:name:object:* and in this way all works.
Apple documentation say this for the method with usingBlock:
The block is copied by the notification center and (the copy) held
until the observer registration is removed.
Sure, I've called removeObserver....
Inside the block in the addObserver method -
usingBlock:^(NSNotification *notification){
/*
do something
*/
[[NSNotificationCenter defaultCenter] removeObserver:self];
}];
As you might have already checked this in documentation -
Be sure to invoke removeObserver: or removeObserver:name:object: before notificationObserver or any object specified in addObserver:selector:name:object: is deallocated.

Posting nsnotification but observer is not hearing it

I am using NSNotifiationCenter, like a 1000 other times, and post a notification, but my observers are not hearing it? What gives?
=== THIS IS IN MY TABLEVIEW ===
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(handleSuccessSocket)
name:kNotificationServiceStartSuccessful
object:self];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(handleFailedSocketConnection)
name:kNotificationSocketFailedToConnect
object:self];
}
=== THIS IS IN MY SOCKETMANAGER (socket manager is a singleton if that matters) ===
-(void)willStartService {
....
[[NSNotificationCenter defaultCenter] postNotificationName:kNotificationServiceStartSuccessful object:nil];
....
}
I have debugged and viewDidLoad is being called in my view. Yes, my willStartService is being called.
You are registering the TableView only for notifications sent by itself. It should be..
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(handleSuccessSocket)
name:kNotificationServiceStartSuccessful
object:nil];
Try setting object:nil in your -addObserver:selector:name:object method calls. What you're doing is telling Notification Center to ONLY listen for notifications that come from the table view instance.
If you don't want to pass nil you'll have to pass an instance of your socket manager.
Check the Docs:
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/nsnotificationcenter_Class/Reference/Reference.html#//apple_ref/occ/instm/NSNotificationCenter/addObserver:selector:name:object:

iOS NSNotificationCenter Observer not being removed

I have the following code within AppDelegate. The purpose being to create a couple of observers, and then call some code. Once that code completes it then posts a notification, and the observer should then remove both observers and call the completion handler.
My issue is that it appears that the observers are not being removed as I expected. The notification is posted, and the NSLog entry is written to console, so I know that the observer is working. However, on the second time of calling, the NSLog is called twice, third time three times etc.
My thoughts are that this is to do with the removal being within the block of code that is running from the observer, however, I am unsure how I can resolve this (if indeed this is what the issue is).
Could someone be so kind as to explain how I can achieve this?
Thanks.
-(void) application:(UIApplication *)application performFetchWithCompletionHandler:
(void (^)(UIBackgroundFetchResult))completionHandler {
[[NSNotificationCenter defaultCenter] addObserverForName:#"fetchDidCompleteNewData" object:nil
queue:nil usingBlock:^(NSNotification *completed) {
//Remove Observers
[[NSNotificationCenter defaultCenter] removeObserver:self
name:#"fetchDidCompleteNewData"
object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:#"fetchDidCompleteNoData"
object:nil];
// Post completion
completionHandler(UIBackgroundFetchResultNewData);
NSLog(#"Background fetch completed... New Data");
}];
[[NSNotificationCenter defaultCenter] addObserverForName:#"fetchDidCompleteNoData" object:nil
queue:nil usingBlock:^(NSNotification *completed) {
//Remove Observers
[[NSNotificationCenter defaultCenter] removeObserver:self
name:#"fetchDidCompleteNoData"
object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:#"fetchDidCompleteNewData"
object:nil];
//post completion
completionHandler(UIBackgroundFetchResultNoData);
NSLog(#"Background fetch completed... No New Data");
}];
GetDetails *getDetails = [[GetDetails alloc] init];
[getDetails backgroundRefresh];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];
return YES;
}
You are not registering self as an object. Moreover, when the block is pushed onto the stack by addObserverForName: the method has not yet returned so the notification is nil.
Make a global object using block, eg
__block __weak id notification;
then,
notification = [[NSNotificationCenter defaultCenter] addObserverForName:#"fetchDidCompleteNewData" object:nil queue:nil usingBlock:^(NSNotification *completed) {
//Remove Observers
[[NSNotificationCenter defaultCenter] removeObserver:notification];
}];
My thoughts are that this is to do with the removal being within the
block of code that is running from the observer, however, I am unsure
how I can resolve this (if indeed this is what the issue is).
Could someone be so kind as to explain how I can achieve this?
Certainly.
You can easily test your theory by not using the addObserverForName:object:queue:usingBlock: method and instead using the addObserver:selector:name:object: method, where the selector is the name of a function you call instead of using a block.
Simply use the API guide for NSNotificationCenter for details about these methods, or in general, since you question was about what other method you could use that does not require a block statement, consulting the API is the first place to check for alternative tools within the class.

Resources