Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle multiple remote-notification click in IOS

I am trying to open different view controllers based on notification click but when push notification is received it automatically runs the controller code in background so when I open the app through app icon/notification from notification centre it loads the view controller immediately but when multiple notifications are received it loads first notification controller irrespective of whichever notification was tapped.

Let's say I've got notification with titles "Evening","Morning" and "Night", it should open "Evening View Controller" when "Evening" notification is tapped but it loads "Night View Controller" when I go back it loads "Morning View Controller" and at last it loads "Evening View Controller". Before notification came, I was on Main Controller and then I moved the app into background.

When I tap on "Morning" notification it doesn't do anything now.

Earlier I tried using addObserver but result is the same so I move to app delegate.

Here is the app delegate code

@interface AppDelegate ()

@end


@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    [[UIApplication sharedApplication]setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];

    // Override point for customization after application launch.
    // Register for Push Notitications, if running iOS 8 or More

    if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) {

        UIUserNotificationType userNotificationTypes = (UIUserNotificationTypeAlert |
                                                        UIUserNotificationTypeBadge |
                                                        UIUserNotificationTypeSound);
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:userNotificationTypes categories:nil];
        [application registerUserNotificationSettings:settings];
        [application registerForRemoteNotifications];

    } else {
        // Register for Push Notifications before iOS 8

        [application registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert |  UIRemoteNotificationTypeSound)];
    }

    [application setStatusBarHidden:YES];

    return YES;
}

// Handle remote notification registration.
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {

    NSLog(@"Device Token %@",[self stringWithDeviceToken:deviceToken]);

    [[NSUserDefaults standardUserDefaults]setObject:[self stringWithDeviceToken:deviceToken] forKey:@"registration_id"];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)err {

    NSLog(@"Error in registration. Error: %@", err);
}


- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {

    NSDictionary *alertInfo = (NSDictionary *) userInfo[@"aps"][@"alert"];
    NSLog(@"%@",alertInfo);

    NSString *alertID = [userInfo valueForKey:@"alertid"];


    if (application.applicationState == UIApplicationStateBackground) {

        [UIApplication sharedApplication].applicationIconBadgeNumber = [UIApplication sharedApplication].applicationIconBadgeNumber + 1;

        NSLog(@"Background Mode");
        NSString *title = alertInfo[@"title"];

        [self openViewController:title];
    }

    if(application.applicationState == UIApplicationStateActive){

        NSLog(@"Active Mode");
           }

    completionHandler(UIBackgroundFetchResultNewData);
    [self performSelector:@selector(sendAckRequest:) withObject:alertID];
}


- (void)openViewController:(NSString *)notificationTitle{

    NSDictionary * userDict = [[NSUserDefaults standardUserDefaults] objectForKey:@"loginUser"];

    if([notificationTitle isEqualToString:@"Exercise"]){

    UINavigationController *navigationController = (UINavigationController *)self.window.rootViewController;

    UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"Main" bundle: nil];

    Excercise *excerciseController = (Excercise*)[mainStoryboard instantiateViewControllerWithIdentifier: @"Excercise"];       
    [navigationController pushViewController:excerciseController animated:YES];
    //[navigationController presentViewController:excerciseController animated:YES completion:nil];

    }else if([notificationTitle isEqualToString:@"Weight"]){

        UINavigationController *navigationController = (UINavigationController *)self.window.rootViewController;

        UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"Main" bundle: nil];

        Weight *weightController = (Weight*)[mainStoryboard instantiateViewControllerWithIdentifier: @"Weight"];           
       [navigationController pushViewController:weightController animated:YES];

        //[navigationController presentViewController:weightController animated:YES completion:nil];

    }else if([notificationTitle isEqualToString:@"MCQ"]){

        UINavigationController *navigationController = (UINavigationController *)self.window.rootViewController;

        UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"Main" bundle: nil];

        QuestionOfTheDay *questionController = (QuestionOfTheDay*)[mainStoryboard instantiateViewControllerWithIdentifier: @"QuestionOfTheDay"];
        questionController.self.dictUser = userDict;
        [navigationController pushViewController:questionController animated:YES]
    }
}

-(void)sendAckRequest:(NSString *)alertID {

    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
    manager.requestSerializer = [AFHTTPRequestSerializer serializer];
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

    NSString *userID =[[defaults objectForKey:@"loginUser"]objectForKey:@"UserId"];
    NSString *serverRegistrationID = [defaults objectForKey:@"server_registration_id"];

    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];

    [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss"];
    NSString *currentDateString = [dateFormatter stringFromDate:[NSDate date]];

    //NSDate *currentDate = [dateFormatter dateFromString:currentDateString];

    //NSDictionary *parameter = @{@"ReminderDateTime":currentDateString};

    NSString *url = [NSString stringWithFormat:@"%@%@/%@/%@/?ReminderDateTime=%@",sendNotificationAck,userID,serverRegistrationID,alertID,currentDateString];


    NSLog(@"url: %@",url);

    [manager GET:url parameters:nil success:^(AFHTTPRequestOperation * _Nonnull operation, id  _Nonnull responseObject) {

        if(operation.response.statusCode == 200)
            NSLog(@"Notification Acknowledged");
        else
            NSLog(@"Notification failed to acknowledge");

    } failure:^(AFHTTPRequestOperation * _Nullable operation, NSError * _Nonnull error) {

        NSLog(@"error: %@",[error localizedDescription]);
    }];
}

- (NSString *)stringWithDeviceToken:(NSData *)deviceToken {

    const char *data = [deviceToken bytes];

    NSMutableString *token = [NSMutableString string];

    for (int i = 0; i < [deviceToken length]; i++) {

        [token appendFormat:@"%02.2hhX", data[i]];
    }

    return token;
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.

    if([UIApplication sharedApplication].applicationIconBadgeNumber!=0)
    [UIApplication sharedApplication].applicationIconBadgeNumber = [UIApplication sharedApplication].applicationIconBadgeNumber - 1;
}

@end
like image 812
moDev Avatar asked Feb 22 '16 08:02

moDev


People also ask

How many local notifications can be scheduled iOS?

As you are already aware, you can schedule maximum of 64 notifications per app. If you add more than that, the system will keep the soonest firing 64 notifications and will discard the other.

What is remote notification in iOS?

Overview. Use remote notifications (also known as push notifications) to push small amounts of data to devices that use your app, even when your app isn't running. Apps use notifications to provide important information to users. For example, a messaging service sends remote notifications when new messages arrive.

How do push notifications work on iOS?

An iOS push notification is a message that pops up on an Apple device such as an iPhone. Before receiving push notifications from an app, iOS device users must explicitly give permission. Once a user opts-in, mobile app publishers can send push notifications to the users' mobile devices.


1 Answers

First, your Remote Notification background mode is enabled, so the notifications get handled in the background. Now the bug is, whenever a notification comes, you push a viewController to the viewController stack, that's why you see three viewControllers stacked.

Second, didReceiveRemoteNotification can be called/handled in different states. StateBackground if the app is in background, StateInactive if user tap the notification from Notification Center, StateForeground if the app is in foreground. You add a check only push the viewController in StateBackground, that's why you don't see any change when tap the notification.

like image 103
dichen Avatar answered Sep 22 '22 22:09

dichen