didReceiveRemoteNotification: fetchCompletionHandler: ouvrir depuis l'icône et la notification push

J'essaie d'implémenter la gestion des notifications push en arrière-plan, mais je n'arrive pas à déterminer si l'user a ouvert l'application à partir de la notification push envoyée plutôt que de l'ouvrir à partir de l'icône.

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { //************************************************************ // I only want this called if the user opened from swiping the push notification. // Otherwise I just want to update the local model //************************************************************ if(applicationState != UIApplicationStateActive) { MPOOpenViewController *openVc = [[MPOOpenViewController alloc] init]; [self.navigationController pushViewController:openVc animated:NO]; } else { ///Update local model } completionHandler(UIBackgroundFetchResultNewData); } 

Avec ce code, l'application s'ouvre sur MPOOpenViewController, quel que soit le mode d'ouverture de l'application par l'user. Comment puis-je faire en sorte que le controller de vue ne soit poussé que s'il ouvre l'application à partir de la notification?

Avec le même code, cela a fonctionné sur iOS 6, mais avec la nouvelle méthode iOS 7, il ne se comporte pas comme je le veux.

Edit: J'essaie de lancer l'application sur iOS 7 maintenant, et nous ne supportons aucune version antérieure à iOS 7. J'ai utilisé ce même code dans la version iOS 6 de la méthode (sans le gestionnaire de complétion) et il s'est comporté la façon dont je m'y attendais. Vous balayer la notification et cela serait appelé. Si vous avez ouvert à partir de l'icône, la méthode ne serait jamais appelée.

Ok je l'ai compris. La méthode est appelée deux fois (une fois lorsqu'elle reçoit le push, et une fois lorsque l'user interagit avec l'icône ou la notification).

 - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { if(application.applicationState == UIApplicationStateInactive) { NSLog(@"Inactive"); //Show the view with the content of the push completionHandler(UIBackgroundFetchResultNewData); } else if (application.applicationState == UIApplicationStateBackground) { NSLog(@"Background"); //Refresh the local model completionHandler(UIBackgroundFetchResultNewData); } else { NSLog(@"Active"); //Show an in-app banner completionHandler(UIBackgroundFetchResultNewData); } } 

Merci à Tim Castelijns pour l'ajout suivant:

Remarque: la raison pour laquelle elle est appelée deux fois est due à la charge utile ayant content_available : 1 . Si vous supprimez la key et sa valeur, elle ne s'exécutera que si vous appuyez sur. Cela ne résoudra pas le problème de tout le monde puisque certaines personnes ont besoin de cette key pour être vraie

@ La solution de MikeV dans Swift 2:

 func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) { if(application.applicationState == UIApplicationState.Inactive) { print("Inactive") //Show the view with the content of the push completionHandler(.NewData) }else if (application.applicationState == UIApplicationState.Background){ print("Background") //Refresh the local model completionHandler(.NewData) }else{ print("Active") //Show an in-app banner completionHandler(.NewData) } } 

@ La solution de MikeV dans Swift 3 (mais avec l'instruction switch):

 func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { switch application.applicationState { case .inactive: print("Inactive") //Show the view with the content of the push completionHandler(.newData) case .background: print("Background") //Refresh the local model completionHandler(.newData) case .active: print("Active") //Show an in-app banner completionHandler(.newData) } }