According to the Apple Docs, in order to find out if a user tapped on your push notification you are supposed to check the applicationState
in application:didReceiveRemoteNotification:
If the value is UIApplicationStateInactive, the user tapped the action button; if the value is UIApplicationStateActive, the application was frontmost when it received the notification.
I have found that this is not always true. For example:
Double-tap the home button to reveal the system tray and enter "fast app switching mode", your application slides up to reveal other running applications and your app is put into the inactive state (even though it's still mostyle visible). If you receive a push notification in this mode your app delegate will still receive the application:didReceiveRemoteNotification:
and at this point your applicationState is UIApplicationStateActive
. According to the docs you should treat it like the user tapped the alert... but in this case they didn't. Not only that, the user didn't even see the push notification (possibly because the top of your application is cut off in this mode).
Does anyone know of a way to detect being in 'fast app switching mode' or handle the notification correctly?
I was able to fix it myself with some nifty checks...
Essentially the key to this whole thing is
-(void)applicationDidEnterBackground:(UIApplication *)application;
This method isn't called when you enter fast app switching (or control center) so you need to setup a check based on it.
@property BOOL isInBackground;
@property (nonatomic, retain) NSMutableArray *queuedNotifications;
And when you receive a notification...
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
UIApplicationState appState = application.applicationState;
// Check if we're in this special state. If so, queue the message up
if (appState == UIApplicationStateInactive && !self.isInBackground) {
// This is a special case in which we're in fast app switching or control center
if (!self.queuedNotifications) {
self.queuedNotifications = [NSMutableArray array];
}
// Queue this to show when we come back
[self.queuedNotifications addObject:userInfo];
}
}
And then when we come back...
- (void)applicationDidBecomeActive:(UIApplication *)application {
application.applicationIconBadgeNumber = 0;
if (!self.isInBackground) {
// Show your notifications here
// Then make sure to reset your array of queued notifications
self.queuedNotifications = [NSMutableArray array];
}
}
One more thing you may want to do is check for this special case of going to fast app switching and the user going somewhere else. I do this just before setting the isInBackground BOOL. I choose to send them as local notifications
-(void)applicationDidEnterBackground:(UIApplication *)application {
for (NSDictionary *eachNotification in self.queuedNotifications) {
UILocalNotification *notification = [self convertUserInfoToLocalNotification:eachNotification];
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
}
self.queuedNotifications = [NSMutableArray array];
self.isInBackground = YES;
}