web-dev-qa-db-ja.com

didReceiveRemoteNotification:fetchCompletionHandler:アイコンから開くvsプッシュ通知

バックグラウンドのプッシュ通知処理を実装しようとしていますが、アイコンから開くのではなく、送信されたプッシュ通知からユーザーがアプリを開いたかどうかを判断するのに問題があります。

- (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を開いています。通知をスワイプしてアプリを開いた場合にのみView Controllerがプッシュされるようにするにはどうすればよいですか?

同じコードで、これはiOS 6で機能しましたが、新しいiOS 7の方法では、思い通りに動作しません。

編集: iOS 7でアプリを実行しようとしていますが、iOS 7より前のバージョンはサポートしていません。iOS6バージョンのメソッドでこの同じコードを使用しました(完了ハンドラー)、それは私が期待する方法で動作しました。通知をスワイプすると、これが呼び出されます。アイコンから開いた場合、メソッドは呼び出されません。

49
Mike V

わかった。このメソッドは、実際には2回呼び出されます(Pushを受信すると1回、ユーザーがアイコンまたは通知を操作すると1回)。

- (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に感謝します。

注:2回呼び出される理由は、ペイロードにcontent_available : 1removeキーとその値の場合、それはタップ時にのみ実行されます。一部の人々はその鍵が真実である必要があるため、これは全員の問題を解決しません

84
Mike V

Swift 3の@MikeVのソリューション(ただし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

Swift 2:の@MikeVのソリューション

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