每次快速解析时第一次对象 id 为零

Posted

技术标签:

【中文标题】每次快速解析时第一次对象 id 为零【英文标题】:object id nil first time every time swift parse 【发布时间】:2015-09-21 13:33:01 【问题描述】:

我正在一个 swift 项目中实现解析。我使用设备的 objectid 作为发送通知的唯一标识符。我为每个用户获取这个值并将其存储在我的数据库中。

我实现了以下方法:

func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) 
        println("get in here every time?")
        let installation = PFInstallation.currentInstallation()
        installation.setDeviceTokenFromData(deviceToken)

        installation.saveInBackground()

        if installation.objectId != nil 
            installation.setObject(installation.objectId!, forKey: "userName")
            updateNotificationIDWebServiceCall(installation.objectId!)
        
        else
            println("object id was nil. Device token was: \(deviceToken).")
            //JLToast.makeText("object id was nil. Device token was: \(deviceToken).").show()
        
        installation.saveInBackground()
    

我在应用启动时成功使用此方法,但我的对象 id 始终为零,这是第一次安装应用时。

如果用户关闭应用程序并重新启动,则 objectid 不再为零,我可以使用每个用户的正确标识符更新我的后端,但是我的问题在于将应用程序置于后台并不使用的人甚至不知道如何杀死一个应用程序。

我该如何解决这个问题?我可以在 didBecomeActive 中添加一些代码吗?我似乎找不到 saveInBackground 方法的回调。

这也是我的 didFinishLaunchingWithOptions:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool 
        Prefs.notificationToShow = true

        // Override point for customization after application launch.
        //UIApplication.sharedApplication().applicationIconBadgeNumber = 0

        if (PFInstallation.currentInstallation().badge != 0) 
            PFInstallation.currentInstallation().badge = 0
            PFInstallation.currentInstallation().saveInBackground()
        
        Parse.setApplicationId("xxx",
            clientKey: "yyy")

        // Register for Push Notitications
        if application.applicationState != UIApplicationState.Background 
            // Track an app open here if we launch with a push, unless
            // "content_available" was used to trigger a background push (introduced in ios 7).
            // In that case, we skip tracking here to avoid double counting the app-open.

            let preBackgroundPush = !application.respondsToSelector("backgroundRefreshStatus")
            let oldPushHandlerOnly = !self.respondsToSelector("application:didReceiveRemoteNotification:fetchCompletionHandler:")
            var pushPayload = false
            if let options = launchOptions 
                pushPayload = options[UIApplicationLaunchOptionsRemoteNotificationKey] != nil
            
            if (preBackgroundPush || oldPushHandlerOnly || pushPayload) 
                PFAnalytics.trackAppOpenedWithLaunchOptions(launchOptions)
            
        
        if application.respondsToSelector("registerUserNotificationSettings:") 
            let userNotificationTypes = UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound
            let settings = UIUserNotificationSettings(forTypes: userNotificationTypes, categories: nil)
            application.registerUserNotificationSettings(settings)
            application.registerForRemoteNotifications()
         else 
            let types = UIUserNotificationType.Badge | UIUserNotificationType.Alert | UIUserNotificationType.Sound
            application.registerForRemoteNotifications()
        

        NSThread.sleepForTimeInterval(1);
        UIApplication.sharedApplication().statusBarHidden = true
        self.window?.makeKeyAndVisible()
        Fabric.with([Twitter(), Crashlytics()])

        return FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)

【问题讨论】:

【参考方案1】:

我不确定为什么安装对象的 objectId 为 nil,但是我有一个替代方法,您可能会感兴趣。

与其将安装的 objectId 保存给用户以获得唯一标识符,不如考虑在每个安装中保存指向当前用户的指针。每个设备都将获得自己的安装对象,并且一个用户可能拥有多个设备。

您需要有一种方法可以将推送通知发送到他们的所有设备,但在您当前的设计下,每个用户仅限于一台设备。

通过将用户指针添加到每个安装对象,您将能够查询和创建用户集以发送通知。

添加一些调试代码以确保 Parse 正确保存安装可能也是值得的。将您的 didRegisterForRemoteNotificationsWithDeviceToken 更改为以下内容:

installation.saveInBackgroundWithBlock  (success: Bool, error: NSError?) -> Void in
    if (success) 
        println("success - didRegisterForRemoteNotificationsWithDeviceToken")
     else 
        //  Log details of the failure
        println("failure - didRegisterForRemoteNotificationsWithDeviceToken")
        println("Error: \(error!) \(error!.userInfo!)")
    
 

【讨论】:

我在应用启动时更新 notificationID,所以如果用户在第二台设备上登录,他们的 id 将被更新并将通知发送到新设备。我们不支持向每位用户多于一台设备发送通知。关于为什么第一次 objectID 为 nil 的任何建议或关于如何在 didbecomeactive 或其他地方获取它的解决方法?我的客户想要这个,因为应用程序的人口统计是可能不会主动杀死应用程序的用户,因此,我后端的 notificationID 仍然为零。检索时有回调吗? 刚刚更新了答案以具有用于保存/调试错误的完成块。我认为问题在于您在didRegisterForRemoteNotificationsWithDeviceToken 中使用了两种不同的保存。我很确定问题在于 objectId 在保存到 Parse 之前将为零。由于保存是在后台异步完成的,因此您当前正在尝试访问尚未完成保存的安装的 objectId 太好了,这是我的想法。将尝试上述不同的方法并报告

以上是关于每次快速解析时第一次对象 id 为零的主要内容,如果未能解决你的问题,请参考以下文章

快速解析firebase时为零

如何为从 .dae 文件导入的对象生成 ID,在下一次加载时将是相同的?

JVM快速调优手册之四: 堆内存分配的CMS公式解析

更改图像的来源使其在第一次单击时其宽度/高度为零

仅找到一次 ID 的核心数据对象

spring组件注册