Using NSNotificationCenter to call method in main app from extensions widget? - ios

I have a widget that I would like to call back to my main app so as to make a call to the server to update data. I looked into delegation, but registering the widget's view controller as a delegate didn't seem very practical. So I moved on to trying to use NSNotificationCenter. I have set it up, but the selector is not being called. In my main iOS app I have this in the viewDidLoad method.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(loadNewData:)
name:kUpdateData
object:nil];
And at the bottom of that file I have this:
/**
* Updates the table when the today widget is called for updated info
**/
- (void)loadNewData:(NSNotification *) notification
{
[self loadTableData];
}
That's in my main app. Now, in my notification center widget/extension, I make this call:
[[NSNotificationCenter defaultCenter]
postNotificationName:kUpdateData
object:nil];
The postNotificationName being passed in, `kUpdateData', is a constant that is resolved to #"updateData". I can see in the debugger that the postNotificationName method is being called, but the main app is not responding to it (regardless of it is in the foreground or the background). What am I doing wrong?
As a side note, the only reason I am doing this is to remove the need for repetitive code and re-implementing things I have already made.

As far as i know extension cant access or call main app methods... what can do is either do the server execution in extension or set a value in shared NSUserDefault so when your app is brought to foreground you can check this value and connect with server accordinly.

Related

Method in viewWillAppear and viewDidLoad didn't loaded

I have created a method to check the status of a server in my viewcontroller, I need to check this, everytime I will open the app.
I call [self checkStatus]; from viewWillAppear and viewDidLoad, but when I open the app, by clicking home button, and I try to open the app again (clicking the app icon in applications) this method is not called. I have a NSLog to view when it is launched or not.
I'm frustrated. Thanks for your help.
You can react to app changes using NotificationCenter:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(doSomething:) name:UIApplicationDidBecomeActiveNotification object:nil];
BTW: don't forget to removeObserver when you don't need it!
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil];
You can also use UIApplicationWillEnterForegroundNotification etc, depending what do you need.
You should read about app lifecycle on Apple Developer pages :). Read:
AppleDeveloperLink Especially section: "Execution States for Apps" to know more about app lifecycle.
StackOverflowLink to know more about view lifecycle.
iOS is not calling those methods again, but the delegate methods in the AppDelegate. You have to propagate the message to your controllers then.
I hope this will help you: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplicationDelegate_Protocol/

How to call method when app enters foreground from background

Is there a simple way to call a method when my app enters the foreground from the background? I have my program call a method "nowYouSeeMe" in the viewDidLoad method, which works great when running the app the first time. When I use the app and then hit home-button it moves to the background as usual. Now when I press app icon and it brings it to the foreground I basically want it to call the nowYouSeeMe method again.
-(void)nowYouSeeMe{
NSLog(#"I'm back");
}
Any ideas??
As already mentioned there is - (void)applicationDidBecomeActive:(UIApplication *)application;in App Delegate, but most of the time you need the information not in your app delegate but your view Controller. Therefore you can use NSNotificationCenter. In your app delegate you could do the following:
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center postNotification:[NSNotification notificationWithName:#"appDidEnterForeground" object:nil]];
Now you can set up listeners in your UIViewControllers setup code:
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self selector:#selector(appDidEnterForeground) name:#"appDidEnterForeground" object:nil];
Now the method appDidEnterForegroundgets called on your view controller whenever the app enters the foreground.
But you don't even need to post the notification yourself because it is already defined in UIApplication. If you scroll down the documentation (UIApplication Class Reference) you see all the notifications declared in UIApplication.h, in your case UIApplicationWillEnterForegroundNotification.
Notice the difference between UIApplicationWillEnterForegroundand UIApplicationDidEnterForeground, but most times you want to use UIApplicationWillEnterForeground, just to set everything up and be ready when the app is displayed.
Of course you should define a constant somewhere for your notifcationname and if you don't need the observer anymore remove it.
Edit: you could also use #selector(nowYouSeeMe) as in your question, missed that
In the appDelegate there is method called applicationDidBecomeActive:(UIApplication *)application it is triggered when your app became active.
Try calling the method via the below app delegate method :
- (void)applicationDidBecomeActive:(UIApplication *)application;
You should implement the applicationWillEnterForeground: method in your AppDelegate, like this:
- (void)applicationWillEnterForeground:(UIApplication *)application
{
[self.controller nowYouSeeMe];
}
provided that you have a reference to that controller as a property in your AppDelegate.
As per everybody else's answer, the application delegate will get a call-out via applicationDidBecomeActive:.
The application will also post the UIApplicationDidBecomeActiveNotification notification. So anyone that isn't the app delegate can just observe that.
You shouldn't use the application delegate as a lazy does-everything singleton if you can avoid it; if it's the one specific view controller that wants to do something only if it is active and the app returns to the foreground then there's no reason to involve the application delegate — it's a behaviour of the view controller, not the application.

Refreshing Parse.com data when the app becomes active

[Edited with solution below]
I want to call a Parse.com query whenever the app becomes active, so that if it's brought up from the foreground, a new set a data will be called.
I realize there is a method for this in the AppDelegate
- (void)applicationDidBecomeActive:(UIApplication *)application {
}
But I want to know how I can put the query information obtained in my AppDelegate and put it in my ViewController where I can display the information.
Any ideas on what I might do? Or if there is another way to make the query when the app becomes active? Thanks.
So here is what I came up with. I had my method (called getData) in the ViewController, and in the viewDidLoad method, I inserted this code
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(getData)
name:UIApplicationDidBecomeActiveNotification object:nil];
And now it works just as I had hoped. Thanks!
This is a really broad question, but what you can do is you can post a notification and make your view controller listen to it.
Then after your app re enter from background, you can post the notification and in the observer method that you implemented in the view controller, you can pull the data from Parse.
See this question to understand the sequence of the method calls.

How to determine when a user has copied text

I am having a hard time how to figure out when a user has selected & copied text the default iOS way:
canPerformSelector works before presenting this menu, but I am interested in knowing after the user has pressed the copy button.
Thank You
Use NSNotification as observer for UIPasteboardChangedNotification: then every time user copies it will call a method which you specified in Notification observer
Something like this
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(ClipBoardChanged) name:UIPasteboardChangedNotification object:nil];
-(void)ClipBoardChanged{
NSLog(#"ClipBoard data changed %#",[UIPasteboard generalPasteboard].string);
}

If add an observer for a notification in the AppDelegate, do I need to bother removing it?

In the AppDelegate's didFinishLaunchingWithOptions:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(contextChanged:)
name:NSManagedObjectContextDidSaveNotification
object:nil];
This is so I can merge changes to the data from other threads.
Question: Do I need to bother removing this listener in applicationWillResignActive or applicationWillTerminate? It doesn't seem like there's a point. I guess I'm asking if it's normal to have listeners like this in the main loop that never get removed.
You can never remove it, but if your app receive a notification (it won't happen in this case) while it is in background the notification will be queued and delivered to the application when it comes up again (if the app isn't killed ofc).
If don't want notifications that happen when your app is in background to be delivered once it comes up you can remove the listener in the methods you pointed out.
In this case, actually, it doesn't matter.

Resources