jabobadilla jabobadilla - 6 months ago 27
Objective-C Question

Update UIMutableUserNotificationAction Button Title on Remote Push Notification

I have an app in iOS where I am sending quick surveys to the users. I want to make use of the new funcionality in iOS 8 where the user interacts directly on the push notification. The user will receive the survey question and respond.

I know you have to construct your actions and categories when starting the app. I have written my code and have been able to successfully perform this so far.

Now, the thing is that the text on the action button will change based on the survey question. I am including the keys and text for the action buttons on the JSON I am sending, but I haven't been able to change the action button titles when receiving the notification.

Is there a way to do this? Here is my code:

I define global variables:

//This will help configure the interactive notifications, so that the user can reply to push notification from out of the app
NSString * const notificationCategoryIdent = @"SURVEY";
NSString * const notificationActionPositiveButton = @"POSITIVE_BUTTON";
NSString * const notificationActionNegativeButton = @"NEGATIVE_BUTTON";


In my AppDelegate:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.

if(pushNotificationPayload) {

urlPushData2 = @"Application was closed";
[self application:[UIApplication sharedApplication] didReceiveRemoteNotification:pushNotificationPayload];

}

//Registrar tipos de aviso para Push Notifications
//if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)]){
if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.0){ //Before iOS 8
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIUserNotificationTypeBadge |
UIUserNotificationTypeSound |
UIUserNotificationTypeAlert)];
}
else {

// define notification actions (In case of categorized remote push notifications)
positiveButton = [[UIMutableUserNotificationAction alloc] init];
[positiveButton setActivationMode:UIUserNotificationActivationModeForeground];
[positiveButton setTitle:notificationActionPositiveButton];
[positiveButton setIdentifier:notificationActionPositiveButton];
[positiveButton setDestructive:NO];
// this action wil be executed without necessity of passcode authentication (if locked)
[positiveButton setAuthenticationRequired:NO];

negativeButton = [[UIMutableUserNotificationAction alloc] init];
[negativeButton setActivationMode:UIUserNotificationActivationModeForeground];
[negativeButton setTitle:notificationActionNegativeButton];
[negativeButton setIdentifier:notificationActionNegativeButton];
[negativeButton setDestructive:NO];
// this action wil be executed without necessity of passcode authentication (if locked)
[negativeButton setAuthenticationRequired:NO];

// define Categories (In case of categorized remote push notifications)
UIMutableUserNotificationCategory *actionCategory;
actionCategory = [[UIMutableUserNotificationCategory alloc] init];
[actionCategory setIdentifier:notificationCategoryIdent];
[actionCategory setActions:@[positiveButton, negativeButton]
forContext:UIUserNotificationActionContextDefault];


NSSet *categories = [NSSet setWithObject:actionCategory];

UIUserNotificationType types = (UIUserNotificationTypeAlert|
UIUserNotificationTypeSound|
UIUserNotificationTypeBadge);

UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:types
categories:categories];

[[UIApplication sharedApplication] registerUserNotificationSettings:settings];

[[UIApplication sharedApplication] registerForRemoteNotifications];

}

//Boolean value for temporary app interruptions
temporaryInactivity = FALSE;

return YES;
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {

NSLog(@"remote notification: %@",[userInfo description]);

NSDictionary *apsInfo = [userInfo objectForKey:@"aps"];

NSString *alert = [apsInfo objectForKey:@"alert"];
//NSLog(@"Received Push Alert: %@", alert);

NSString *sound = [apsInfo objectForKey:@"sound"];
NSLog(@"Received Push Sound: %@", sound);
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);

application.applicationIconBadgeNumber = [[apsInfo objectForKey:@"badge"] integerValue];

self.mainUrl = [userInfo valueForKey:@"url"];
urlPushData = [NSString stringWithFormat:@"%@", mainUrl];
//NSLog(@"urlPushData: %@",urlPushData);

self.mainUrl2 = [userInfo valueForKey:@"url2"];
urlPushData2 = [NSString stringWithFormat:@"%@", mainUrl2];
//NSLog(@"urlPushData2: %@",urlPushData2);

NSString *category = [apsInfo objectForKey:@"category"];
NSLog(@"category: %@", category);
if ([category isEqualToString:notificationCategoryIdent]) {
NSLog(@"button1: %@", [apsInfo objectForKey:@"positiveButton"]);
NSLog(@"button2: %@", [apsInfo objectForKey:@"negativeButton"]);
NSString *stringPositiveButton = [apsInfo objectForKey:@"positiveButton"];
NSString *stringNegativeButton = [apsInfo objectForKey:@"negativeButton"];
[positiveButton setTitle:stringPositiveButton];
[negativeButton setTitle:stringNegativeButton];
}
else {
if (![urlPushData2 isEqualToString:@"Application was closed"]) {
[UIApplication sharedApplication].applicationIconBadgeNumber = [UIApplication sharedApplication].applicationIconBadgeNumber - 1;
[[NSUserDefaults standardUserDefaults] setObject:urlPushData2 forKey:@"pushNotificationURL"];
[[NSUserDefaults standardUserDefaults] setObject:alert forKey:@"pushNotificationURLName"];
[[NSUserDefaults standardUserDefaults]synchronize];
if (NSClassFromString(@"UIAlertController")) {
//make and use a UIAlertController
UIAlertController *alertView = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@"%@",appNameLink]
message:[NSString stringWithFormat:@"Has recibido una nueva nota: %@. ¿Deseas verla?",alert]
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *Cancel = [UIAlertAction actionWithTitle:@"No"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
[UIApplication sharedApplication].applicationIconBadgeNumber = [UIApplication sharedApplication].applicationIconBadgeNumber - 1;
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"pushNotificationURL"];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"pushNotificationURLName"];
[[NSUserDefaults standardUserDefaults]synchronize];
}
];
UIAlertAction *OK = [UIAlertAction actionWithTitle:@"Sí"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
[UIApplication sharedApplication].applicationIconBadgeNumber = [UIApplication sharedApplication].applicationIconBadgeNumber - 1;

self.url = [[NSUserDefaults standardUserDefaults] objectForKey:@"pushNotificationURL"];
self.urlName = [[NSUserDefaults standardUserDefaults] objectForKey:@"pushNotificationURLName"];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"pushNotificationURL"];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"pushNotificationURLName"];
[[NSUserDefaults standardUserDefaults]synchronize];

[self setupNavigationControllerApp];
}
];
[alertView addAction:Cancel];
[alertView addAction:OK];

[[[[[UIApplication sharedApplication] delegate] window] rootViewController] presentViewController:alertView animated:YES completion:nil];
}
else {
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:[NSString stringWithFormat:@"%@",appNameLink] message:[NSString stringWithFormat:@"Has recibido una nueva nota: %@. ¿Deseas verla?",alert] delegate:self cancelButtonTitle:@"No" otherButtonTitles:@"Sí", nil];
[alertView show];
}
} else {
[UIApplication sharedApplication].applicationIconBadgeNumber = [UIApplication sharedApplication].applicationIconBadgeNumber - 1;
//self.url = [[NSUserDefaults standardUserDefaults]objectForKey:@"pushNotificationURL"];
self.url = urlPushData2;
self.urlName = alert;
[self setupNavigationControllerApp];
}
}

}


- (void) application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void (^)())completionHandler {

if ([identifier isEqualToString:notificationActionPositiveButton]) {

//Testing the action button
self.url = @"http://www.google.com";
self.urlName = @"hello";
[self setupNavigationControllerApp];

}
else if ([identifier isEqualToString:notificationActionNegativeButton]) {

//Testing the action button
self.url = @"http://www.yahoo.com";
self.urlName = @"goodbye";
[self setupNavigationControllerApp];

}

// Must be called when finished
completionHandler();

}


And this is my JSON:

{"aps":
{"alert":"Who's your favorite pop singer?",
"badge":1,
"sound":"default",
"category":"SURVEY",
"positiveButton":"Katy Perry",
"negativeButton":"Miley Cyrus"
},
"url":"http://www.pretechmobile.com",
"url2":"http://goo.gl/U9p1y"
}

Answer

I am sorry, but you cannot change the title of the buttons dynamically. They are tied to the category in which they are stored when you register for notifications.

A possible workaround could be to present the two options in the text of the message labeled with an 'A' and a 'B' and have your buttons with titles 'Option A' and 'Option B'. Something like this:

---------------------------------
|Who's your favorite pop singer?|
|A: Katy Perry    B: Miley Cyrus|
---------------------------------
|   Option A    |   Option B    |
---------------------------------

Also, If you have yes/no questions, you can create a category for them with the options 'Yes' and 'No' and label your notifications with this category.

I hope this helps a bit.