Can I watch an NSNotification from another class? - iphone

I'm trying to get my head around NSNotificationCenter. If I have something like this in my App Delegate:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(something:)
name:#"something"
object:nil];
-----
-(void)something:(NSNotification *) notification
{
// do something
}
Can I somehow watch this in another view controller? In my case, I'd like to watch it in a view controller with a table, and then reload the table when a notification is received. Is this possible?

Yes you can do it like this:
In class A : post the notification
[[NSNotificationCenter defaultCenter] postNotficationName:#"DataUpdated "object:self];
In class B : register first for the notification, and write a method to handle it.
You give the corresponding selector to the method.
//view did load
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(handleUpdatedData:) name:#"DataUpdated" object:nil];
-(void)handleUpdatedData:(NSNotification *)notification {
NSLog(#"recieved");
}

Yes you can that is the whole purpose of NSNotification, you just have to add the View Controller you want as an observer exactly the same way you did on your App Delegate, and it will receive the notification.
You can find more information here: Notification Programming

Of course it's possible, that's the whole point of notifications. Using addObserver:selector:name:object: is how you register to receive notifications (you should do this in your table view controller), and you can use postNotificationName:object:userInfo: to post a notification from any class.
Read Notofication Programming Topics for more info.

You can register to observe notifications in as many classes as you like. You simply need to "rinse and repeat". Include the code to register as an observer in your view controller (perhaps in viewWillAppear:) and then reload the tableView from your method:
- (void)viewWillAppear:(BOOL)animated {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(something:) name:#"something" object:nil];
}
-(void)something:(NSNotification *) notification
{
[self.tableView reloadData];
}
It's also a good idea to de-register the view controller once you no longer need the notifications:
- (void)viewWillDisappear:(BOOL)animated {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}

You should just add that as an Observer and give a different selector method if you want that viewController to behave differently when that notification is posted.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(somethingOtherThing:)
name:#"something"
object:nil];
-(void)somethingOtherThing:(NSNotification *) notification
{
// do something
}

Related

selector from inside a delegate method triggers twice

A weird issue occurs after a delegate method of my static lib is fired. first of all, the project has a sub project which is a static library (xcode 4.6 ios 6.x). The static lib fires its own delegates according to the event.
the App implements the delegate method of the static lib. in the implementation i use the following to access the UI elements and trigger other events. Didgetnotified is the delegate method of the lib.
- (void)didGetNotified
{
dispatch_async(dispatch_get_main_queue(), ^{
[self parseData];
NSNotificationCenter *notifyCenter = [NSNotificationCenter defaultCenter];
[notifyCenter addObserver:self
selector:#selector(updateUI)
name:#"updateUIN"
object:nil];
});
}
-(void) parseData {
//parse data and its ready now and send notification
[[NSNotificationCenter defaultCenter] postNotificationName:#"updateUIN" object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"updateUIN" object:nil];
}
-(void) updateUI {
//this method gets fired twice mostly
}
the problem is that the updateUI gets called twice. i cant see what i'm doing wrong. is it something with the threading? the static lib delegate is not on the main thread. but i use the dispatch on the main thread. can some one please explain?
thank in advance.
after intensive debugging i have found that the adding oberserver was actually happened twice. the solution was to remove the oberserver before adding it in case of WIFI disconnects and the date stream goes thru 3G and that case my delegate was fired twice and registered oberver 2 times.
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"updateUIN" object:self];
NSNotificationCenter *notifyCenter = [NSNotificationCenter defaultCenter];
[notifyCenter addObserver:self
selector:#selector(updateUI)
name:#"updateUIN"
object:self];

- (void)applicationDidEnterBackground:(UIApplication *)application

I want to cancel url connection when applicationDidEnterBackground is called. But I don't know how to save a connection in a whole scope of application. I created a few url connections in other view controllers, but I'd like to cancel them in AppDelegate. How can I do this?
You may add observer to UIApplicationDidEnterBackgroundNotification in your class which create the connection. Try this:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(enterBackground) name:UIApplicationDidEnterBackgroundNotification object:nil];
remember call this
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil];
in your class's dealloc
I believe your NSURLConnections will be killed when your app enters the background.
If you want to keep track of all NSURLConnections, you need to keep track of them yourself by adding them to a NSSet, NSArray, or some other datastructure, and looping through them closing them. You could also have a class that inherits or composes a NSURLConnection. This datastructure would handle adding itself to a queue, and you could clean up when the app exits.
It is better to stop the connections before app becomes inactive instead of applicationDidEnterBackground.
Answer is use notifications:
-(void)init
{
//
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(closeConnection) name:UIApplicationWillResignActiveNotification object:nil];
//
}
-(void)closeConnections
{
// [urlConnection cancel];
}

postNotificationName not calling observer method

I am trying to call a method within an uiview from AppDelegate using the NSNotificationCenter to no avail..
AppDelegate.m
[[NSNotificationCenter defaultCenter] postNotificationName:#"ProcessDidComplete" object:items];
Then via MainStoryboard, the main view is loaded which controller class is MainViewController
in MainViewController.h viewDidLoad i have
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(ProcessDidComplete:) name:#"ProcessDidComplete" object:nil];
and then the method
- (void) ProcessDidComplete:(NSNotification *)pNotification
but it never gets called.
Thanks for any help!
just change a way..
First add observer
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(ProcessDidComplete:) name:#"ProcessDidComplete" object:nil];
Then Post Notification
[[NSNotificationCenter defaultCenter] postNotificationName:#"ProcessDidComplete" object:items];
Finally remove in viewWillDisappear
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"ProcessDidComplete" object:nil];
Your code looks okay, which makes me wonder where in your app delegate you post the notification?
If you post the notification before you add the observer in the view controlller, then the notification will never be received. Can you not send the message to the main view controller directly, i.e., as a property, rather than using notifications?
Just wanted to note here that iOS notification names are case-sensitive:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(handUpdate:) name:#"scheduleUpdated" object:nil];
will not respond to:
[[NSNotificationCenter defaultCenter] postNotificationName:#"ScheduleUpdated" object:items];
(as I spent the last 20 minutes figuring out...)

Present view when local notification is received

With iOS 5 and storyboarding, what is the best way to present a view when the user enters the app after having received a localnotification?
I have read that using the NSNotificationCenter is the way to do it but is that also so with storyboarding and segues?
This is exactly how I implemented it. In the AppDelegate's didFinishLaunchingWithOptions: method, I did the following:
UILocalNotification *notification =
[launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
[self application:application didReceiveLocalNotification:notification];
I did this so that I could keep logic in a single place. In the didreceiveLocalNotification: method, I then used the NSNotificationCenter:
// Let another view handle the display
NSNotificationCenter * nc = [NSNotificationCenter defaultCenter];
[nc postNotificationName:#"SHOW_VERSE"
object:self
userInfo:notification.userInfo];
The view that handles the display is the first UIViewController for the Storyboard. In that class, in the viewDidLoad method:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(receivedLocalNotification:)
name:#"SHOW_VERSE"
object:nil];
This works very well for me. Hope it helps.

Pass An Object Between 2 View Controllers

I'm trying to pass an object between 2 VCs, from a popover to the detail view of split view controller.
I think I need to use NSNotificationCenter.
I tried this but can't seem to get it to work.
In didSelectRow of popover
[[NSNotificationCenter defaultCenter] postNotificationName:#"PassObject" withObject:objectToPass];
In detail VC
- (void) didReceiveNotificationPassObject:(NSNotification*)notification
{
YourObjectClass *theObject = (YourObjectClass*)notification.object;
}
- (void)viewDidLoad
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(didReceiveNotificationPassObject:) name:#"PassObject" object:nil];
}
Probably just a typo when entering the question but in the first line where you post the notification
[[NSNotificationCenter defaultCenter] postNotificationName:#"PassObject" withObject:objectToPass];
the method signature is wrong - it should be 'object:objectToPass' not 'withObject:objectToPass'. The line you have there will compile with a warning and crash at runtime.
Aside from that all the logic seems fine.
What is the problem you are facing? Does didReceiveNotificationPassObject: hit? If it doesn't, you could verify that viewDidLoad executes before didSelectRow.
Use [[NSNotificationCenter defaultCenter] postNotificationName:#"PassObject" object:objectToPass]; instead of [[NSNotificationCenter defaultCenter] postNotificationName:#"PassObject" withObject:objectToPass];
Also, don't forget to removeObserver in viewDidUnload.
HTH,
Akshay
A fast and easy solution to notify with multiple parameters is to call the notification it like this
[[NSNotificationCenter defaultCenter] postNotificationName:#"shareButton" object:#"camera"];
Where "camera" acts like your parameter. Then
- (void)shareButton:(id)sender
{
NSString *kindOf = [sender object];
if ([kindOf isEqualToString:#"camera"]) {
// Your code goes here
}
}