didReceiveRemoteNotification:fetchCompletionHandler:从图标vs推送通知打开

时间:2014-02-28 02:50:42

标签: ios ios7 push-notification apple-push-notifications uiapplicationdelegate

我正在尝试实施后台推送通知处理,但我在确定用户是否从发送的推送通知中打开应用程序时遇到了问题,而不是从图标中打开它。

- (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版本中使用了相同的完整代码方法(没有完成处理程序),它的行为方式与我期望的方式相同。你要刷通知,这将被调用。如果从图标打开,则永远不会调用该方法。

3 个答案:

答案 0 :(得分:80)

好的我明白了。该方法实际上被调用两次(一次是在接收推送时,一次是在用户与图标或通知交互时)。

- (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的补充:

  

注意:它被调用两次的原因是由于Payload有   content_available : 1。如果你删除键及其值,那么它只会在点击时运行。这不会解决每个人的问题,因为有些人需要这个关键是真的

答案 1 :(得分:11)

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

答案 2 :(得分:9)

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

}