DidReceiveRemoteNotification: fetchCompletionHandler: открыть из значка против push-уведомления

Я пытаюсь выполнить обработку уведомлений фонового push, но у меня возникают проблемы с определением того, открыл ли пользователь приложение из push-уведомления, которое было отправлено, а не открывало его из значка.

- (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);
}

С помощью этого кода приложение открывается в MPOOpenViewController независимо от того, как пользователь открывает приложение. Как я могу сделать это так, чтобы контроллер представления был нажат только в том случае, если они открывают приложение для прокрутки уведомления?

С тем же кодом это работало на iOS 6, но с новым методом iOS 7, он не ведет себя так, как я хочу.

Изменить: Сейчас я пытаюсь запустить приложение на iOS 7, и мы не поддерживаем какую-либо версию до iOS 7. Я использовал тот же самый точный код в версии iOS 6 (без обработчика завершения), и он вел себя так, как я ожидал. Вы проведете уведомление, и это будет вызвано. Если вы открыли из значка, метод никогда не будет вызываться.

Ответ 1

Хорошо, я понял это. Метод фактически вызывается дважды (один раз, когда он получает push, и один раз, когда пользователь взаимодействует со значком или уведомлением).

- (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);

    }
}

Спасибо Tim Castelijns за следующее дополнение:

Примечание: причина, по которой он дважды вызван, связан с полезной нагрузкой, имеющей content_available : 1. Если вы удалите ключ и его значение, он будет работать только при нажатии. Это не решит проблему, так как некоторым людям нужен этот ключ, чтобы быть правдой.

Ответ 2

Решение @MikeV в 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)
    }

}

Ответ 3

Решение @MikeV в Swift 3 (но с оператором 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)
    }
}