This is my code.
Here create the observer to Notification called Example into ViewController
- (void)addObserverExample
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(example:)
name:#"Example"
object:nil];
}
- (void)example:(NSNotification *)notification{
NSLog(#"Example!!!");
}
From viewDidLoad register my observer
- (void)viewDidLoad
{
[self addObserverExample];
}
In my second ViewController. When tapped a button excute this code:
[[NSNotificationCenter defaultCenter] postNotificationName:#"Example" object:self.dictKeys userInfo:nil];
The problem I have is that the notification is never executed.
Any idea.
Have created demo for NSNotificationCenter as per your question and it's working fine for me. Here it is the link of that code: NSNotificationCenter Demo
- (void)viewDidLoad {
[super viewDidLoad];
[self addObserverExample];
}
- (void)addObserverExample
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(example:)
name:#"Example"
object:nil];
}
- (void)example:(NSNotification *)notification{
NSLog(#"Example!!!");
NSLog(#"%#",notification.userInfo);
}
- (IBAction)btnFireNotification:(id)sender {
[[NSNotificationCenter defaultCenter] postNotificationName:#"Example" object:nil userInfo:#{#"key" : #"value"}];
}
I believe the problem you're having may be related to the fact that in your second view controller, you're passing self.dictKeys in the object parameter.
If you want to pass data via the NSNotificationCenter, you should use the userInfo parameter instead.
Darshan's example does this the correct way.
Related
I'm not sure about how to achieve this and hence i'm asking this question.
I have 2 ViewController(VC) named abVC and xyVC.
abVC contains only TableView and xyVC contains only a button.
When i tap a button on xyVC, it should reload tableview inside abVC without moving to that abVC.
Is it possible ? If yes.. then please help me,How to do that?
You can do it with both block and NSNotification.
With block you can implement it as follows:
make a property as follows in xyzVC.h:
#property(strong,nonatomic)void(^callBack)();
Synthesize this property in xyzVC.m
#synthesize callBack
Call this block in Buttons click event
- (IBAction)btnClick:(UIButton *)sender {
if (callBack)
{
callBack();
}
}
Implement it in abcVC where you want call back:
[abVC setCallBack:^{
//reload your tableview here
}];
With NSNotification you can implement it as follows:
Register for receiving notification in abcVC.m
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(reloadTableView) name:#"ReloadTable" object:nil];
- (void)reloadTableView{
// Reload your tableview here
}
Now post the notification from xyzVC
- (IBAction)btnClick:(UIButton *)sender {
[[NSNotificationCenter defaultCenter] postNotificationName:#"ReloadTable" object:nil];
}
Note: If you are using NSNotification then don't forget to remove it when your view controller is dismissed
I hope this will help you :)
Add this line in your button action method
[[NSNotificationCenter defaultCenter] postNotificationName:#"ReloadTable" object:nil];
Add this code where you have implemented table, so in abVC:
inside viewDidLoad:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(reloadTableViewData) name:#"ReloadTable" object:nil];
Add following method
- (void)reloadTableViewData{
[self.myTableView reloadData];
}
Implement dealloc method (to prevent crash)
- (void)dealloc{
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"ReloadTable" object:nil];
}
I am facing an issue with NSNotificationCenter.
I am not able to send message and receive message using NSNotificationCenter in latest ios 8.4 (XCode 6.4)
Please check the following code:
1) I want to send data using first view controller to another view.
so i have written the following code in first viewcontroller:
When user btn clicked method as following :
- (IBAction)btnClicked:(id)sender
{
[self postNotification];
[self performSegueWithIdentifier:#"asGo" sender:self];
}
-(void)postNotification{
[[NSNotificationCenter defaultCenter] postNotificationName:#"MyNotification" object:self];
}
2) In Second view controller i have added observer in ViewWillApper as following :
-(void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:YES];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(eventListenerDidReceiveNotification:)
name:#"MyNotification"
object:nil];
}
-(void)eventListenerDidReceiveNotification:(NSNotification*)txt
{
NSLog(#"i got notfication:");
}
so eventListenerDidReceiveNotification is not called while come on view.
But i am not getting above log while i come on second vc with navigation
As others have noted, NSNotificationCenter doesn't work like a post office. It only delivers notifications if someone actually listens to them at the moment they arrived. This is the reason your eventListenerDidReceiveNotification method is not being called: you add an observer in viewWillAppear, which is called after the segue (I assume that you're using segues because of the performSegueWithIdentifier method in your code) is finished, so it's definitely called after postNotification has been called.
So, in order to pass data via NSNotificationCenter you have to add an observer before you post a notification.
The following code is completely useless and unnecessarily overcomplicated, you shouldn't do anything like that, but since you keep insisting on using a scheme like this, here you go:
//Didn't test this code. Didn't even compile it, to be honest, but it should be enough to get the idea.
NSString * const SOUselessNotificationName = #"MyUselessNotification";
#pragma mark - FIRST VC
#interface SOFirstVC : UIViewController
#end
#implementation SOFirstVC
NSString * const SOasGoSegueIdentifer = #"asGo";
- (IBAction)btnClicked:(id)sender {
[self performSegueWithIdentifier:SOasGoSegueIdentifer sender:self];
}
-(void)postNotification {
[[NSNotificationCenter defaultCenter] postNotificationName:SOUselessNotificationName object:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifer isEqualToString:SOasGoSegueIdentifer]) {
SOSecondVC *destinationVC = (SOSecondVC *)segue.destinationViewController;
[destinationVC registerToReceiveNotificationsFromObject:self];
[self postNotification];
}
}
#end
#pragma mark - SECOND VC
#interface SOSecondVC : UIViewController
-(void)registerToReceiveNotificationsFromObject:(id)object;
#end
#implementation SOSecondVC
-(void)registerToReceiveNotificationsFromObject:(id)object {
[[NSNotificationCenter defaultCenter] addObserver:self selector:(eventListenerDidReceiveUselessNotification:) name:SOUselessNotificationName object:object];
}
-(void)eventListenerDidReceiveUselessNotification:(NSNotification*)uselessNotification {
NSLog(#"I got a useless notfication! Yay!");
}
-(void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#end
NSNotificationCenter basically has 3 steps
Adding Observer like [[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(open:) name:#"OpenDetail" object:nil];
Posting Notification [[NSNotificationCenter defaultCenter] postNotificationName:#"OpenDetail" object:self];
Removing Observer [[NSNotificationCenter defaultCenter] removeObserver:self name:#"OpenDetail" object:nil];
I think you are posting your notification and then later adding observer while it's vie versa. You have to add observer first then post notification.
HTH
First you have to setup the data you want to send
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:myObject forKey:#"aKey"];
Then you post it with the data like so:
[[NSNotificationCenter defaultCenter] postNotificationName: #"MyNotification" object:nil userInfo:userInfo];
And finally you read the data off the notification:
-(void)eventListenerDidReceiveNotification:(NSNotification*)notification
{
NSLog(#"i got notification:");
NSDictionary *userInfo = notification.userInfo;
NSString *myObject = [userInfo objectForKey:#"aKey"];
}
My code:
-(void)viewWillAppear:(BOOL)animated {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(handleKeyboard:) name:UIKeyboardWillChangeFrameNotification object:nil];
}
-(void)viewWillDisappear:(BOOL)animated {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
-(void)handleKeyboard:(NSNotification*)notification {
NSLog(#"triggered");
}
See:
The disappearing handler is triggered once as normal, but 3 times when appears. Is this a iOS bug?
Possibly not helpful for your problem but you need to be calling [super viewWill… for your overrides.
-(void)viewWillAppear:(BOOL)animated
-(void)viewWillDisappear:(BOOL)animated
From the docs.
If you override this method, you must call super at some point in
your implementation.
I have 2 observers registered. One of them is in appDelegate and the other is in myViewController. When I am in myViewController, I just expect to get two notifications, one from appDelegate which executes some method globally, the other one from myViewController which executes some other method. But, only the one in appDelegate gets called. If I remove the observer in appDelegate, the observer in myViewController gets called. Actually, I can just use the observer method in appDelegate and find out the current view controller and execute the code of the method in myViewController. But, I just don't wanna mess appDelegate. The same code for both of them but I remove the observer in myViewController when viewWillDisappear() method gets called. Any ideas? Thanks.
appDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(someMethod:)
name:#"someName"
object:nil];
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"someName"
object:nil
userInfo:someUserInfo];
}
- (void)someMethod:(NSNotification *)notification
{
// gets called
}
myViewController
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(someMethod:)
name:#"someName"
object:nil];
}
- (void)viewWillDisappear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter] removeObserver:self
name:#"someName"
object:nil];
[super viewWillDisappear:animated];
}
- (void)someMethod:(NSNotification *)notification
{
// not called
}
In the code below you're posting before observing
(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"someName"
object:nil
userInfo:someUserInfo];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(someMethod:)
name:#"someName"
object:nil];
}
* Original *
Plenty of possible issues here:
one the notification Name could be spelt wrong = #"someName" - If this is going to be observe red from other classes, think about creating an
in a .h (that both classes import)
include
extern NSString * const XXXSomeNameForSomeNotification;
in the corresponding .m
NSString * const XXXSomeNameForSomeNotification = #"someName";
That's one way to ensure they're all observing/posting the right notification
If that's not your issue then try adding observing the notification from the viewDidLoad or another method that's called prior to viewDidAppear as it could be that it's not observing you notification when it's actually posted. Add break points to observe this.
Looks like, Your notification is posted before view is loaded. See adding some logs.
OR try this -
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[[NSNotificationCenter defaultCenter] postNotificationName:#"someName"
object:nil
userInfo:someUserInfo];
});
I think as per you posted code the reason is
- (void)viewWillDisappear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter] removeObserver:self
name:#"someName"
object:nil];
[super viewWillDisappear:animated];
}
The method above will remove the notification observing if the current view is not on screen.
Also you may want to move the
[[NSNotificationCenter defaultCenter] removeObserver:self
name:#"someName"
object:nil];
to
- (void) dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self
name:#"someName"
object:nil];
}
that way you only stop observing the notification when you remove the view controller form memory. You may want to check in the method that's called if you're on screen.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to tell when controller has resumed from background?
How to refresh View after user enters applicationWillEnterForeground?
I want to complete recall for example HomeViewController.
I have and update function in HomeViewController and I want when user enters to call update function and reload table data.
Any class can register to UIApplicationWillEnterForegroundNotification, and react accordingly. It's not reserved to the app delegate, and helps for better separation of source code.
Create a viewDidLoad method like this for your HomeViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(yourUpdateMethodGoesHere:)
name:UIApplicationWillEnterForegroundNotification
object:nil];
}
// Don't forget to remove the observer in your dealloc method.
// Otherwise it will stay retained by the [NSNotificationCenter defaultCenter]...
- (void) dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
If your ViewController is a tableViewController your could also directly call the reload data function:
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:[self tableView]
selector:#selector(reloadData)
name:UIApplicationWillEnterForegroundNotification
object:nil];
}
- (void) dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
Or you could use a block:
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillEnterForegroundNotification
object:nil
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification *note) {
[[self tableView] reloadData];
}];
You could declare a property in your app delegate class that would point to the HomeViewController object. Then you can call your update function in applicationWillEnterForeground.