解析 PFUser.currentUser returns 零 - Swift

Parse PFUser.currentUser returns nil - Swift

我正在使用 Parse 登录我的用户。当我的应用程序打开时,我的 LaunchVieWController 确定用户是否已经登录:

override func viewDidLoad() {
    super.viewDidLoad()

    //Make sure cached users don't have to log in every time they open the app
    var currentUser = PFUser.currentUser()
    println(currentUser)
    if currentUser != nil {
        dispatch_async(dispatch_get_main_queue()) {
            self.performSegueWithIdentifier("alreadySignedIn", sender: self)
        }
    } else {
        dispatch_async(dispatch_get_main_queue()) {
            self.performSegueWithIdentifier("showSignUpIn", sender: self)
        }
    }
}

如果用户已经登录,他们将被带到下面描述的 table 视图。如果他们没有登录,他们将被带到一个视图,在该视图中他们可以转到注册视图或登录视图。

我的注册工作非常好,注册用户然后将他们重定向到 table 视图。 这是注册函数(它与登录函数在一个单独的控制器中):

func processSignUp() {

    var userEmailAddress = emailAddress.text
    var userPassword = password.text

    // Ensure username is lowercase
    userEmailAddress = userEmailAddress.lowercaseString

    // Add email address validation

    // Start activity indicator
    activityIndicator.hidden = false
    activityIndicator.startAnimating()

    // Create the user
    var user = PFUser()
    user.username = userEmailAddress
    user.password = userPassword
    user.email = userEmailAddress

    user.signUpInBackgroundWithBlock {
        (succeeded: Bool, error: NSError?) -> Void in
        if error == nil {

            dispatch_async(dispatch_get_main_queue()) {
                self.performSegueWithIdentifier("signInToNavigation", sender: self)
            }

        } else {

            self.activityIndicator.stopAnimating()

            if let message: AnyObject = error!.userInfo!["error"] {
                self.message.text = "\(message)"
            }               
        }
    }
}

我的登录函数是这样的:

@IBAction func signIn(sender: AnyObject) {
    var userEmailAddress = emailAddress.text
    userEmailAddress = userEmailAddress.lowercaseString
    var userPassword = password.text

   PFUser.logInWithUsernameInBackground(userEmailAddress, password:userPassword) {
        (user: PFUser?, error: NSError?) -> Void in
        if user != nil {
            dispatch_async(dispatch_get_main_queue()) {
                self.performSegueWithIdentifier("signInToNavigation", sender: self)
            }
        } else {
            if let message: AnyObject = error!.userInfo!["error"] {
                self.message.text = "\(message)"
            }
        }
    }
}

用户登录后,他们将被转到 table 视图。在那个 table 视图中,我试图在以下函数中访问当前用户对象,因为我想根据用户身份加载不同的数据:

override func queryForTable() -> PFQuery {
    var query = PFQuery(className:"MyClass")
    query.whereKey("userID", equalTo: PFUser.currentUser()!)
    return query
}

当我尝试使用某个用户登录时,出现以下错误:"fatal error: unexpectedly found nil while unwrapping an Optional value"。 PFUser.currentUser() 对象似乎为零。

当用户在 注册 后被发送到 table 视图时,PFUser.currentUser() 对象已设置并完美运行。

我的猜测是,这是因为 PFUser.logInWithUsernameInBackground 在后台发生,而我的查询试图在加载 PFUser.currentUser() 对象之前获取它。无论如何我可以解决这个问题吗?在 table 视图中,需要 PFUser.currentUser() 的值来加载 table 数据。我能否以某种方式确保 PFUser.currentUser() 在函数被调用之前分配给当前用户对象(例如,通过不在后台线程中加载用户)?

非常感谢所有帮助!

编辑:我已经用我的更多代码更新了这个post,以帮助突出显示我可能遗漏的任何错误。

您可以尝试检查是否 PFUser.currentUser() != nil 以确保它在登录后立即设置。如果没有立即设置,您就知道存在更深层次的登录问题。

此外,请尝试删除围绕您对 segue 的调用的 dispatch_async(dispatch_get_main_queue()){ 包装器。

这是不必要的(logInWithUsernameInBackground 已经 returns 到主线程)而且我有一种预感,它正在创建一个竞争条件,其中没有首先设置本地对象,因为 Parse 不能做任何事情 post-调用清理,因为您正准备进入主线程。

我发现出现这个问题是因为 segue signInToNavigation 是从登录按钮连接的,而不是从登录视图控制器本身连接的。这导致在执行登录功能之前执行 segue,因此在加载 table 视图时尚未分配 PFUser.currentUser() 对象。我通过重新布线 segues 解决了这个问题。我这边的愚蠢失误。

感谢 Ryan Kreager 和 Wain 花时间帮我解决这个问题!