Distinct when local notification was tapped and when received - ios

I have app that send local notifications.
So I have two scenarios.
Application is in foreground, notification center is dragged out. Notification is recived. Notification center is being hidden.
Application is in foreground, notification center is dragged out. Notification is recived. Notification is selected.
My code to handel notifications
AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UILocalNotification* notification = launchOptions[UIApplicationLaunchOptionsLocalNotificationKey];
//When App is launched from notification
[self setupLocalNotification:notification.userInfo];
}
-(void) application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
NSLog(#"USER INFO %#",notification.userInfo);
[self setupLocalNotification:notification.userInfo];
}
-(void)setupLocalNotification:(NSDictionary*)userInfo {
UIApplicationState state = [[UIApplication sharedApplication] applicationState];
if ( state == UIApplicationStateInactive || state == UIApplicationStateBackground){
[[NSUserDefaults standardUserDefaults] setObject:userInfo forKey:#"localNotification"];
//This is for situation when I'm deep in navigation controller and this also trigger viewWillAppear in ViewController
[[((MainPanelViewController*)[[self window] rootViewController]) startNC] popToRootViewControllerAnimated:false];
} else {
//something
}
}
** MainPanelViewController**
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
//This is for situation when currently in ViewController
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(beacomeActive) name:UIApplicationDidBecomeActiveNotification object:nil];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self checkLocalNotification];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil];
}
- (BOOL) checkLocalNotification{
NSDictionary* userInfo = [[NSUserDefaults standardUserDefaults] objectForKey:#"localNotification"];
if (userInfo != nil) {
NSLog(#"Notification");
[self performSegueWithIdentifier:#"ShowNotification" sender:self];
return true;
}
return false;
}
Problem
I don't know how to distinct those two situations. Because every time notification is received when App is inactive then method performSegueWithIdentifier is being called.

Related

Update UITableView when Push Notification received

I have a simple application as RSS-reader.
How do I better organize to update feed when receiving Push Notification?
1) Call FirstViewController from didReceiveRemoteNotification and update feed?
2) Send value from didReceiveRemoteNotification to FirstViewController, and in FirstViewController update feed?
I'm posting NSNotification from AppDelegate
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
{
[[NSNotificationCenter defaultCenter]
postNotificationName:#"appDidReceiveRemoteNotification"
object:self
userInfo:userInfo];
}
And listening to that notification in my ViewControllers, like this
- (void)remoteNotificationReceived:(NSNotification *)aNotification
{
NSDictionary *userInfo = aNotification.userInfo;
// Update your views here
}
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(remoteNotificationReceived:)
name:#"appDidReceiveRemoteNotification"
object:nil];
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}

Passing data received from a push notification from the AppDelegate to a ViewController

In my app, there's a collection view displaying a set of images retrieved from a web service. Each image has tags. So the app has the ability to filter images using tags as well.
Now I'm trying to add push notifications to this app. A push notification is sent when new images have been added to the server. These images are tagged say, latest. I'm passing that tag as the message via a push notification and what I need is when the user taps on the push notification to open the app, it should load the latest new images to the collection view.
I'm half way done. I receive the push notification with the message successfully to the didReceiveRemoteNotification method in the AppDelegate.m file. Now I need to pass it on to the view controller where the collection view is. I'm stuck at this point. I can't figure out how to send it over to the view controller.
I tried declaring a property in the App delegate, assign the message value to it and referring it from the view controller but it didn't work. I tied delegates, notification center, user defaults but nothing worked.
Can anyone please tell me how to accomplish this?
Thank you.
Edit:
Here's my code. The last method I tried was the local notifications.
AppDelegate.m
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"PushNotificationMessageReceivedNotification" object:nil userInfo:userInfo];
}
ViewController.m
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(remoteNotificationReceived:) name:#"PushNotificationMessageReceivedNotification"
object:nil];
}
- (void)remoteNotificationReceived:(NSNotification *)notification
{
NSLog(#"Notification: %#", notification.userInfo);
NSString *msg = [[notification.userInfo valueForKey:#"aps"] valueForKey:#"alert"];
self.label.text = msg;
}
Case 1: if your app is background and user launches app with notification click then you have the check if app launched form notification or normal
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
NSDictionary *remoteNotificationPayload = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (remoteNotificationPayload) {
[[NSNotificationCenter defaultCenter] postNotificationName:#"notification" object:nil userInfo:remoteNotificationPayload];
}
return YES; }
Case2: If your app is in forground notification will be received in didReceiveRemoteNotification
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
NSLog(#"userinfo %#",userInfo);
[[NSNotificationCenter defaultCenter] postNotificationName:#"notification" object:nil userInfo:userInfo];
}
Now you and add a observer in any controller with Local notification and do what you wand to do
I don't know it will work or not,its only my suggestion. I did't tried it before but in your case may be it work
user NSUserDefaults for this.
in your appDelegate.m
[[NSUserDefaults standardUserDefaults] setObject:imageArrayFromServer forKey:#"MyAppSpecificGloballyUniqueString"];
in your viewController.m
NSArray *myArray = [[NSUserDefaults standardUserDefaults] objectForKey:#"MyAppSpecificGloballyUniqueString"];

Erase fields when application goes back to foreground

I'm a very beginner in iOS developpment. What I what to do is to delete the content of 2 fields (login and password) when application moves to foregroung after being in background.
To be clear: if a user put the application in foreground and is on the login screen, fields corrsponding to login and password should be empty.
What I have done: I have add a listener to the AppDelegate file that is detecting well background/foreground actions. Here is the code:
- (void)applicationWillEnterForeground:(UIApplication *)application {
#try {
UINavigationController *navigationController = (UINavigationController*)self.window.rootViewController;
UIViewController *cont = [[navigationController viewControllers] objectAtIndex:[navigationController viewControllers].count - 1];
if ([cont isKindOfClass:[LoginScreenController class]]){
NSLog(#"[AppDelegate] ok, we're on login screen");
}
else {
NSLog(#"[AppDelegate] No, we're not");
}
}
#catch(NSException *exp)
{
NSLog(#"[AppDelegate] Fail: %#",exp);
}
}
But when executing the code, I reach an issue linked to BaseRootView... First, do I proceed the appropriate way and then, how to do what I want to do? That's to say, how to erease the fields (I have a function to do this in the LoginController class, so how to call it prperly?)
Thanks !
Put your code in
- (void)applicationDidBecomeActive:(UIApplication *)application
You should use this method instead of
- (void)applicationWillEnterForeground:(UIApplication *)application
when you update user interface this is what this method is for.
Hope this help.
// EXTENDED
Can you try put this code to UIApplicationDidBecomeActiveNotification:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(updateUI)
name:UIApplicationDidBecomeActiveNotification
object:nil];
And add this code to AppDelegate:
-(void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil];
}
and add:
-(void)updateUI
{
//Add code to update ui
}
You can do this by posting a notification. Here in the place of yourFunctionName write your function name which is to erase the fields
In login view controller write this following code.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
// Custom initialization
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(yourFunctionName) name:#"removeText" object:nil];
}
return self;
}
Now post a notification in applicationWillEnterForeground method.
- (void)applicationWillEnterForeground:(UIApplication *)application
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"removeText" object:nil];
}
Hope this helps you.

UIApplicationState active in background on iOS 7

I setup a background task with beginBackgroundTaskWithExpirationHandler:^{ } and even after ending the task using
if ([[UIDevice currentDevice] isMultitaskingSupported]) {
[[UIApplication sharedApplication] endBackgroundTask:backgroundTaskID];
backgroundTaskID = UIBackgroundTaskInvalid;
}
NSLog(#"App State -- %d", [[UIApplication sharedApplication] applicationState]);
if([[UIApplication sharedApplication] applicationState] == UIApplicationStateActive)
{
//OpenGL operations
}
what I get is UIApplicationStateActive. Is this a bug ? How else do I determine the app is indeed in background ?
Instead of relying on the applicationState value, how about posting a custom notification at the end of the background task?
Set up as an observer for your custom notification:
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(backgroundTaskDidFinish:) name:#"BackgroundTaskDidFinish" object:<either nil or the object that will post the notification>];
}
Post your custom notification when the background task completes
if ([[UIDevice currentDevice] isMultitaskingSupported]) {
[[UIApplication sharedApplication] endBackgroundTask:backgroundTaskID];
backgroundTaskID = UIBackgroundTaskInvalid;
[[NSNotificationCenter defaultCenter] postNotificationName:#"BackgroundTaskDidFinish" object:self]
}
Respond to the notification, which your app should receive when it really returns to an active state
- (void)backgroundTaskDidFinish:(NSNotification *)notification
{
//OpenGL operations
}
Alternatively, you could look for one of the other notification messages that would indicate that your app is truly in an active state.
For instance, add your object as an observer for UIApplicationWillEnterForeground. Set a BOOL value when you receive that notification. Then, look for that BOOL value along with the UIApplicationState value.
Of course, at some point you'll have to clear the BOOL - say, when you're starting that background task - so it will be NO unless the app really did become active.
You can try to determine it with NSNotification:
- (void)viewDidLoad {
[super viewDidLoad];
UIApplication *app = [UIApplication sharedApplication];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:app];
}
- (void)applicationWillResignActive:(NSNotification *)notification {
//do what you want when your app is in background
}

View Controller method for lock button pressed?

Is there an available view controller method that is called when the user presses the lock button? I'm looking for something like viewDidDisappear: or viewWillDisappear:, but specific to the case of the lock button being pressed.
A notification called UIApplicationDidEnterBackgroundNotification is posted when the user locks their phone. Here's how to listen for it:
In viewDidLoad: of your ViewController:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(screenLocked) name:UIApplicationDidEnterBackgroundNotification object:nil];
Then, define a method (mine was called screenLocked above) and write code you want to be executed when the screen is locked.
-(void)screenLocked{
//do stuff
}
Also, to do some necessary cleanup, add this method to your ViewController too.
-(void)dealloc{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil];
}
Try this :
- (void)applicationDidEnterBackground:(UIApplication *)application
{
UIApplicationState state = [application applicationState];
if (state == UIApplicationStateInactive) {
NSLog(#"Sent to background by locking screen");
} else if (state == UIApplicationStateBackground) {
NSLog(#"Sent to background by home button/switching to other app");
}
}

Resources