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

时间:2022-09-07 08:22:16

I'm trying to implement background push notification handling, but I'm having issues with determining whether the user opened the app from the push notification that was sent as opposed to opening it from the icon.

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

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

With this code, the app is opening to the MPOOpenViewController regardless of how the user opens the app. How can I make it so that the view controller is only pushed if they open the app from swiping the notification?

使用此代码,无论用户如何打开应用程序,该应用程序都会打开MPOOpenViewController。我怎样才能使视图控制器只有在他们通过刷通知打开应用程序时才会被推送?

With the same code, this worked on iOS 6, but with the new iOS 7 method, it doesn't behave how I want it to.

使用相同的代码,这可以在iOS 6上运行,但是使用新的iOS 7方法,它并不像我想要的那样。

Edit: I'm trying to run the app on iOS 7 now, and we are not supporting any version prior to iOS 7. I used this same exact code in the iOS 6 version of the method (without the completion handler) and it behaved the way I'd expect it to. You'd swipe the notification and this would get called. If you opened from the icon, the method would never be called.

编辑:我正在尝试在iOS 7上运行应用程序,我们不支持iOS 7之前的任何版本。我在方法的iOS 6版本中使用了相同的完全代码(没有完成处理程序)并且它表现得很好我希望它的方式。你要刷通知,这将被调用。如果从图标打开,则永远不会调用该方法。

3 个解决方案

#1


76  

Ok I figured it out. The method is actually called twice (once when it receives the push, and once when the user interacts with the icon or the 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);

    }
}

Thanks Tim Castelijns for the following addition:

感谢Tim Castelijns的以下补充:

Note: the reason it's called twice is due to the Payload having content_available : 1. If you remove the key and its value, then it will only run upon tapping. This will not solve everyone's problem since some people need that key to be true

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

#2


8  

@MikeV's solution in Swift 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


6  

@MikeV's solution in Swift 3 (but with switch statement):

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

#1


76  

Ok I figured it out. The method is actually called twice (once when it receives the push, and once when the user interacts with the icon or the 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);

    }
}

Thanks Tim Castelijns for the following addition:

感谢Tim Castelijns的以下补充:

Note: the reason it's called twice is due to the Payload having content_available : 1. If you remove the key and its value, then it will only run upon tapping. This will not solve everyone's problem since some people need that key to be true

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

#2


8  

@MikeV's solution in Swift 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


6  

@MikeV's solution in Swift 3 (but with switch statement):

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