In a class when a method is performed, I have put this:
[[NSNotificationCenter defaultCenter] postNotificationName:#"locationFromZipFound" object:array];
and in the class that I wish to recieve the notification I have this:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(getZipLocation:)
name:#"locationFromZipFound"
object:nil];
The problem is, this is never called:
-(void)getZipLocation:(NSNotification *)notification; {
NSLog(#"Zip received and put into array!");
NSArray *location = [notification object];
}
Any ideas?
Thanks in advance.
Never mind! I was trying to register for notifications in a method, and it seemed like it didn't like that. I just registered for notifications in viewDidLoad and all seems to be well!
I copy and pasted your code and it works great for me.
I put the postNotification on a Button and the addObserver on viewDidAppear:animated.
Related
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];
In my Class X I post a Notification like this:
[[NSNotificationCenter defaultCenter] addObserver:viewController
selector:#selector(doThis:)
name:#"myNotification"
object:nil];
[[NSNotificationCenter defaultCenter] postNotificationName:#"myNotification" object:nil];
In my Class Y I recieve it like this:
- (void) doThis: (NSNotification *) notification {
NSLog(#"It works.");
[uiTextView resignFirstResponder]; }
The console shows the NSLog message but my UITextView does not hide its keyboard.
(In e.g. viewDidLoad the resignFirstResponder/becomeFirstResponder works.)
Is there any special thing I need to do?
FWIW, in most, but not all, cases, observers should be added and removed by the observer itself, not by a separate object. (What happens if the observer goes away before the separate object, and fails to have the observer properly removed? Or vice-versa? It makes it all too easy to either leak observers or crash on notifications to deallocated objects.)
Anyhow, first thing's first: have you verified that uiTextView is not nil and points at the first responder? I rather suspect that uiTextView is not what you think it is.
As Conrad says, observers should be added and removed by themselves...
Use the best practice to define the name of the notifications as static constants like follows:
static NSString *const kMyNotification = #"myNotification";
Why? because there is a risk that both #"myNotification" might be two different objects and then the notificationName is different and you won't receive the notification. Since I always declare them as static constants I have never had issues with NSNotifications.
Then use it like this:
To register the observer
[[NSNotificationCenter defaultCenter] addObserver: self
selector: #selector(doThis:)
name: kMyNotification
object: nil];
To post the notification
[[NSNotificationCenter defaultCenter] postNotificationName: kMyNotification
object: nil];
To remove the observer:
[[NSNotificationCenter defaultCenter] removeObserver: self];
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
}
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
}
}
I'm trying to get one instance of using NSNotificationCenter with addObserver and postNotificationName but I can't work out why it won't work.
I have 2 lines to code to add the observer and send the message in 2 different classes
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(newEventLoaded:) name:#"Event" object:nil];
and
[[NSNotificationCenter defaultCenter]postNotificationName:#"Event" object:self];
If I set the name to nil it works fine becuase it's just a broadcast, when i try and define a notification name the messages never get through.
All my code makes use of NSNotifications like so:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(updateView) name:#"ScanCompleted" object:nil];
[[NSNotificationCenter defaultCenter] postNotificationName:#"ScanCompleted" object:nil];
The first one is registering the notification and the second posting of the notification.
Basically it's all to do with the order of execution. If you've executed postNotificationName before addObserver, then this is an easy problem to have. Use breakpoints and step through the code :)
Your first breakpoint should stop here:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(updateView:) name:#"ScanCompleted" object:nil];
Then here:
[[NSNotificationCenter defaultCenter]postNotificationName:#"ScanCompleted" object:self];
Also, make sure the selector has a colon on. Because it's method signature will be:
- (void)updateView:(NSNotification *)notification;
I had the same problem.
The reason is that I called removeObserver method at
- (void)viewDidDisappear:(BOOL)animated{
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter removeObserver:self];
}
So check whether if you had called removeObserver before postNotification.
Tips: You can search the keyword "removeObserver" to find if you had called this function.
Change this:
[[NSNotificationCenter defaultCenter]postNotificationName:#"Event" object:self];
to this:
[[NSNotificationCenter defaultCenter]postNotificationName:#"Event" object:nil];
If your first notification is registered properly, newEventLoaded should be called.
I had a similar issue and my problem was due to the notification being called on another thread. This solved my problem.
dispatch_async(dispatch_get_main_queue(),^{
[[NSNotificationCenter defaultCenter]postNotificationName:#"Event" object:self];
});
Have you tried any other names but #"Event" and nil? Just to be sure, you could define your event names in one file and include that into both notification registration and sending. For example:
Header file:
extern NSString * const NOTE_myEventName;
Source file:
NSString * const NOTE_myEventName = #"MyEventName";
Registration:
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(handleMyEvent:)
name:NOTE_myEventName
object:nil];
Notification sending:
[[NSNotificationCenter defaultCenter]
postNotificationName:NOTE_myEventName object:nil];
I successfully fixed my "NSNotification not being sent when postNotificationName: called" crash.
I found the real bug is in notification message handler.
The postNotificationName and addObserver are all right as the first post of this thread.