简体   繁体   中英

View Controller loads before data is pulled from firebase login - Swift

I am having trouble getting data to load correctly in my ViewDidAppear method when using a Firebase login. I want the user to press the login button, the app to retrieve the user's information from Firebase, and then display it in the next view controller (which is part of a new tab bar controller).

When I use breakpoints, I can see that the new view appears and THEN the data is pulled from Firebase. I need the data to be loaded from Firebase before the view appears.

Here is my code for the login button:

let userSettings = NSUserDefaults.standardUserDefaults()

@IBAction func signInButton(sender: AnyObject) {

    ref.authUser(emailTextField.text, password: passwordTextField.text) { (error, authData) -> Void in

        if error != nil {

            let accountError = UIAlertController(title: "Error logging in", message: "Please try again", preferredStyle: .Alert)
            accountError.addAction(UIAlertAction(title: "Ok", style: .Default, handler: nil))
            self.presentViewController(accountError, animated: true, completion: nil)


        }  else {                

            userID = ref.authData!.uid

            userSettings.setObject(userID!, forKey: "firebaseUserID")

            let playNumberRef = Firebase(url:"https://(removed for security).firebaseIO.com/users/\(userID!)/playNumber")


            //Check Firebase for the user's last playnumber and set it in the user defaults

            playNumberRef.observeSingleEventOfType(.Value, withBlock: { snap in

                //Convert type AnyObject to NSNumber so that we can check its value

                if let checkPlay = snap.value as? NSNumber {

                    userSettings.setInteger(Int(checkPlay), forKey: "playNumber")

                }})

Here is my code in the viewWillAppear method:

var playNumber = userSettings.integerForKey("playNumber")

dayCounterLabel.text = "Day \(playNumber)"

When the view first appears, the dayCounterLabel.text has not been updated. If I navigate to a different tab and then navigate back, it updates.

How can get the data to save into the user defaults prior to the view appearing?

This is a common issue:

Firebase is asynchronous and viewWillAppear is occurring before Firebase has had time to return the data. This code

 playNumberRef.observeSingleEventOfType

is a block and the app should not proceed to show the next view until that block has the returned data.

In other words, show the next view from inside that block

I don't know how the rest of your code is set up, but here's a quickie example (untested so don't copy paste)

Suppose we have a loginViewController that lets the user login, and then a mainViewController for the main app view after the user logs in.

In the AppDelegate we have

func showMainView() {

    let storyboard = NSStoryboard(name: "Main", bundle: nil)

    self.mainVC = (storyboard.instantiateControllerWithIdentifier("MainViewController") as? NSViewController)!

    self.mainVC.showWindow(self)

}

so in your case the block could be modified thusly:

playNumberRef.observeSingleEventOfType(.Value, withBlock: { snap in

   if let checkPlay = snap.value as? NSNumber {

     userSettings.setInteger(Int(checkPlay), forKey: "playNumber")

     let appDelegate = NSApplication.sharedApplication().delegate as! AppDelegate

     appDelegate.showMainView() //prepare to sho the main view

     self.view.window?.close() //get rid of this one

}})

So the main view controller is only displayed when Firebase has had a time to return the data and the vars are populated.

 if let checkPlay = snap.value as? NSNumber {
     dispatch_async(dispatch_get_main_queue(),{
        userSettings.setInteger(Int(checkPlay), forKey: "playNumber")
     })
 }})

Try this, it can help you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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