web-dev-qa-db-fra.com

didReceiveRemoteNotification: fetchCompletionHandler: ouverture de l'icône vs notification Push

J'essaie d'implémenter la gestion des notifications Push en arrière-plan, mais je rencontre des problèmes pour déterminer si l'utilisateur a ouvert l'application à partir de la notification Push envoyée par opposition à 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 quelle que soit la façon dont l'utilisateur ouvre l'application. Comment puis-je faire en sorte que le contrôleur de vue ne soit poussé que s'il ouvre l'application en glissant 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 souhaite.

Edit: J'essaie d'exécuter l'application sur iOS 7 maintenant, et nous ne prenons en charge aucune version antérieure à iOS 7. J'ai utilisé ce même code exact dans la version iOS 6 de la méthode (sans le gestionnaire d'achèvement) et il s'est comporté comme je m'y attendais. Vous feriez glisser la notification et cela serait appelé. Si vous ouvrez à partir de l'icône, la méthode ne sera jamais appelée.

49
Mike V

Ok je l'ai compris. La méthode est en fait appelée deux fois (une fois lorsqu'il reçoit le Push et une fois lorsque l'utilisateur 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 il est appelé deux fois est due au fait que la charge utile a content_available : 1. Si vous supprimez la clé et sa valeur, elle ne s'exécutera qu'après avoir appuyé sur. Cela ne résoudra pas le problème de tout le monde car certaines personnes ont besoin de cette clé pour être vraie

84
Mike V

@ 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)
    }
}
11
SuperGlenn

@ 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)
    }

}
9
Marie Amida