我在iOS 8上的推送通知中添加了两个操作按钮:Accept
按钮和Deny
按钮。这两个按钮都不会打开应用程序,但根据按下的按钮,将会发出不同的服务器请求。这是我的设置:
+ (void)requestForPushNotificationToken {
UIApplication *application = [UIApplication sharedApplication];
// if ios 8 or greater
if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) {
UIMutableUserNotificationAction *acceptAction = [[UIMutableUserNotificationAction alloc] init];
[acceptAction setActivationMode:UIUserNotificationActivationModeBackground];
[acceptAction setTitle:@"Accept"];
[acceptAction setIdentifier:@"ACCEPT_ACTION"];
[acceptAction setDestructive:NO];
[acceptAction setAuthenticationRequired:NO];
UIMutableUserNotificationAction *denyAction = [[UIMutableUserNotificationAction alloc] init];
[denyAction setActivationMode:UIUserNotificationActivationModeBackground];
[denyAction setTitle:@"Deny"];
[denyAction setIdentifier:@"DENY_ACTION"];
[denyAction setDestructive:NO];
[denyAction setAuthenticationRequired:NO];
UIMutableUserNotificationCategory *actionCategory = [[UIMutableUserNotificationCategory alloc] init];
[actionCategory setIdentifier:@"ACTIONABLE"];
[actionCategory setActions:@[acceptAction, denyAction]
forContext:UIUserNotificationActionContextDefault];
NSSet *categories = [NSSet setWithObject:actionCategory];
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert) categories:categories];
[application registerUserNotificationSettings:settings];
} else if ([application respondsToSelector:@selector(registerForRemoteNotificationTypes:)]) { // ios 7 or lesser
UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
[application registerForRemoteNotificationTypes:myTypes];
}
}
然后,在我的委托方法中,我指定当用户按下其中一个操作按钮时要采取的操作:
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void (^)())completionHandler {
if ([identifier isEqualToString:@"ACCEPT_ACTION"]) {
// Sending a request to the server here
}
else if ([identifier isEqualToString:@"DENY_ACTION"]) {
// Sending a request to the server here
}
if (completionHandler) {
completionHandler();
}
}
理想情况是用户不需要在整个过程中启动应用程序;按Accept
或Deny
将对服务器进行不同的调用。使用上面的代码,我看到按钮操作的行为非常不稳定:
有人可以帮我弄清楚导致这种不稳定行为的原因是什么吗?提前谢谢。
答案 0 :(得分:12)
我终于找到了原因。事实上,它有时是有效的,有时是不可能的,应该早点给我提示。
根据application:handleActionWithIdentifier:forRemoteNotification:completionHandler:
的Apple文档:
此方法的实现应执行与指定标识符关联的操作,并在完成后立即在completionHandler参数中执行该块。在实施结束时未能执行完成处理程序块将导致您的应用程序被终止。
我在application:handleActionWithIdentifier:forRemoteNotification:completionHandler
方法的末尾调用了完成处理程序。但是,我在处理程序代码中向服务器发送请求的事实意味着我的end of implementation
不仅仅是在方法的末尾;我真正的目的在于回应我的要求。我编写它的方式,完成处理程序和回调都在两个不同的线程上,当完成处理程序在它到达回调之前运行时,它将失败。
因此解决方案是将完成处理程序移动到请求的回调方法中,即真正的“实现结束”。像这样:
[MyClient sendRequest:userInfo withSuccessBlock:^(id responseObject){
NSLog(@"Accept - Success");
if (completionHandler) {
completionHandler();
}
} withFailureBlock:^(NSError *error, NSString *responseString) {
NSLog(@"Accept - Failure: %@",[error description]);
if (completionHandler) {
completionHandler();
}
}];
答案 1 :(得分:0)
在iOS8上,您需要致电
[application registerForRemoteNotifications];
来自application:didRegisterUserNotificationSettings:
:
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
[application registerForRemoteNotifications];
}