iOS 8 推送通知操作按钮 - 当应用程序在后台时,handleActionWithIdentifier 中的代码并不总是运行
Posted
技术标签:
【中文标题】iOS 8 推送通知操作按钮 - 当应用程序在后台时,handleActionWithIdentifier 中的代码并不总是运行【英文标题】:iOS 8 push notification action buttons - code in handleActionWithIdentifier does not always run when app is in background 【发布时间】:2015-04-25 18:56:08 【问题描述】:我在 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
将对服务器进行不同的调用。使用上面的代码,我看到按钮操作的行为非常不稳定:
谁能帮我找出导致这种不稳定行为的原因?提前致谢。
【问题讨论】:
º您好,您可以共享通知的有效负载吗?当远程通知到来时,我无法设置操作按钮...>. @SophySwicz 在我的服务器代码中相关的有效负载是payloadBuilder.category("ACTIONABLE");
您需要添加ACTIONABLE
类别
最后,我的有效载荷结束于:"aps":"alert":"loc-key":"KEY_BODY_ALERT_VOTE_MORNING","category":"ACTIONABLE"并且在设置 UIMutableUserNotificationCategory 时使用 UIUserNotificationActionContextDefault
【参考方案1】:
我终于找到原因了。它有时有效,有时无效,这一事实应该更早地给我提示。
根据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();
];
【讨论】:
【参考方案2】:在 iOS8 上你需要调用
[application registerForRemoteNotifications];
来自application:didRegisterUserNotificationSettings:
:
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
[application registerForRemoteNotifications];
【讨论】:
我已经这样做了,抱歉我没有粘贴那些代码。推送通知在所有其他情况下都有效,只是操作按钮处理程序有问题。以上是关于iOS 8 推送通知操作按钮 - 当应用程序在后台时,handleActionWithIdentifier 中的代码并不总是运行的主要内容,如果未能解决你的问题,请参考以下文章
当用户通过向上滑动强制退出应用程序时,可操作的推送通知不会出现在 iOS 8+ 设备上