【问题标题】:didReceiveRemoteNotification: fetchCompletionHandler: open from icon vs push notificationdidReceiveRemoteNotification:fetchCompletionHandler:从图标打开与推送通知
【发布时间】:2014-03-31 20:51:41
【问题描述】:

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

- (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 版本的方法(没有完成处理程序),它的行为方式与我期望的一样。你会滑动通知,这会被调用。如果从图标打开,则永远不会调用该方法。

【问题讨论】:

  • 看起来还不错。当您从图标打开应用程序时,永远不会调用此方法。那么究竟你面临的问题是什么,或者你还想实现什么?
  • @ArpitKumarKulshrestha 这不是真的。由于应用程序支持后台远程通知,因此在应用程序仍在后台时调用此方法。例如,如果我在此处设置断点并关闭应用程序。然后当我收到推送时,它会在应用程序仍然关闭的情况下到达断点。这在 iOS6 中没有发生
  • 在您的问题行中“使用相同的代码,这适用于 iOS 6,但使用新的 iOS 7 方法,它的行为并不符合我的预期。”。指定它在哪个 iOS 中运行?
  • 您不能在 iOS 6 中执行此操作。stackoverflow.com/questions/20487890/…
  • 我在 iOS 7 上运行它。在 iOS 7 之前我们不支持任何东西

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


【解决方案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 的以下补充:

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

【讨论】:

  • 非常感谢!!!!这非常有帮助!!!!任何不知道如何实现后台远程通知的人,请参阅此页面:developer.xamarin.com/guides/cross-platform/…
  • 只是一点优化。如果您正在调用 completionHandler(UIBackgroundFetchResultNewData);在每个条件中,您可以无条件地调用它并删除其中两行。
  • UIApplicationStateInactive 状态的问题在于,它不仅发生在用户与通知交互打开应用程序的情况下,还发生在应用程序处于Inactive 状态时,例如:当收到短信/电话,显示通知中心或控制中心。因此,在上述情况下导航到视图时会导致误报。
  • 非常感谢您写下每个通知都会收到两次电话!节省了我的一天:) 但是,请记住在您的项目中启用后台获取和远程通知 -> 功能 -> 后台模式
  • 注意:它被调用两次的原因是因为 PN 有content_available=true。如果您删除它或将其设置为 false,它只会运行一次。这不会解决每个人的问题,因为有些人需要那把钥匙是真的
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-17
      • 2016-12-11
      • 1970-01-01
      • 2017-07-31
      相关资源
      最近更新 更多