简体   繁体   English

解析PFUser.currentUser返回nil - Swift

[英]Parse PFUser.currentUser returns nil - Swift

I am logging in my users using Parse. 我正在使用Parse登录我的用户。 As my app opens my LaunchVieWController determines whether users are already signed in or not: 当我的应用程序打开时,我的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)
        }
    }
}

If users are already signed in they are taken to the table view described below. 如果用户已登录,则会将其带到下面描述的表视图中。 If they are not logged in, they are taken to a view in which they can go to the signup view or the login view. 如果他们未登录,则会将他们带到可以转到注册视图或登录视图的视图中。

My signup works perfectly fine, and signs up users and then redirects them to the table view. 我的注册工作完全正常,并注册用户,然后将它们重定向到表视图。 Here is the signup function (it is in a separate controller from the login function): 这是注册功能(它与登录功能位于一个单独的控制器中):

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

My login function looks like so: 我的登录功能如下:

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

After users log in they are sent to a table view. 用户登录后,会将其发送到表格视图。 In that table view I am trying to access the current user object in the following function, as I want to load different data based on who the user is: 在该表视图中,我试图访问以下函数中的当前用户对象,因为我想根据用户是谁加载不同的数据:

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

When I try to log in with a user I get thrown the following error: "fatal error: unexpectedly found nil while unwrapping an Optional value". 当我尝试使用用户登录时,我会抛出以下错误:“致命错误:在解开可选值时意外发现nil”。 It seems like the PFUser.currentUser() object is nil. 似乎PFUser.currentUser()对象是nil。

When users are sent to the table view after signing up the PFUser.currentUser() object is set and works perfectly. 注册后,当用户被发送到表视图 ,PFUser.currentUser()对象已设置并且工作正常。

My guess is that this is because of the fact that the PFUser.logInWithUsernameInBackground is happening in the background and that my query is trying to get the PFUser.currentUser() object before it has been loaded. 我的猜测是,这是因为PFUser.logInWithUsernameInBackground正在后台发生,我的查询试图在加载之前获取PFUser.currentUser()对象。 Is there anyway I can work around this issue? 无论如何我可以解决这个问题吗? In the table view the value of PFUser.currentUser() is needed to load the table data. 在表视图中,需要PFUser.currentUser()的值来加载表数据。 Can I somehow make sure that PFUser.currentUser() gets assigned with the current user object before the function gets called (for example, by not loading in users in the background thread)? 我可以以某种方式确保在调用函数之前为PFUser.currentUser()分配当前用户对象(例如,通过不在后台线程中的用户加载)?

All help is much appreciated! 非常感谢所有帮助!

EDIT: I've updated this post with some more of my code to help highlight any bug that I may be missing. 编辑:我已经用我的一些代码更新了这篇文章,以帮助突出我可能遗漏的任何错误。

I discovered that this problem appeared because the segue signInToNavigation was wired from the Login-button, instead from the login view controller itself. 我发现出现这个问题是因为s​​egue signInToNavigation是从Login-button连接的,而不是登录视图控制器本身。 This resulted in the segue being executed before the login function was executed, and therefore the PFUser.currentUser() object was not yet assigned when the table view loaded. 这导致在执行登录功能之前执行segue,因此在加载表视图时尚未分配PFUser.currentUser()对象。 I solved this by rewiring the segues. 我通过重新布线来解决这个问题。 Stupid slip-up on my side. 愚蠢的滑倒在我身边。

Thanks to Ryan Kreager and Wain for taking time to help me figure out this issue! 感谢Ryan Kreager和Wain花时间帮我解决这个问题!

You can try checking if PFUser.currentUser() != nil instead to make sure it's being set right after login. 您可以尝试检查PFUser.currentUser() != nil ,以确保在登录后立即设置它。 If it's not being set right off the bat, you know there is a deeper login problem. 如果它没有立即设置,你知道有更深层次的登录问题。

Also, try removing the dispatch_async(dispatch_get_main_queue()){ wrapper around your call to the segue. 另外,尝试删除dispatch_async(dispatch_get_main_queue()){包围您对segue的调用的包装器。

It's unnecessary (logInWithUsernameInBackground already returns to the main thread) and I have a hunch that it's creating a racing condition where the local object is not being set first because Parse can't do any post-call cleanup since you're going right for the main thread. 这是不必要的(logInWithUsernameInBackground已经返回到主线程)并且我有一种预感,它正在创建一个竞争条件,其中本地对象没有被设置为首先因为Parse不能进行任何呼叫后清理,因为你正在寻找主线程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM