在从firebase登录中提取数据之前加载View Controller - Swift

时间:2016-04-16 18:15:10

标签: ios swift firebase viewwillappear

使用Firebase登录时,我无法在ViewDidAppear方法中正确加载数据。我希望用户按下登录按钮,该应用程序从Firebase检索用户的信息,然后将其显示在下一个视图控制器中(它是新标签栏控制器的一部分)。

当我使用断点时,我可以看到新视图出现,然后数据从Firebase中提取。我需要在视图出现之前从Firebase加载数据。

以下是登录按钮的代码:

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

                }})

以下是viewWillAppear方法中的代码:

var playNumber = userSettings.integerForKey("playNumber")

dayCounterLabel.text = "Day \(playNumber)"

当视图首次出现时,dayCounterLabel.text尚未更新。如果我导航到另一个选项卡然后导航回来,它会更新。

如何在视图出现之前将数据保存到用户默认值中?

2 个答案:

答案 0 :(得分:2)

这是一个常见问题:

Firebase是异步的,并且在Firebase有时间返回数据之前会发生viewWillAppear。这段代码

 playNumberRef.observeSingleEventOfType

是一个块,应用程序不应继续显示 next 视图,直到该块包含返回的数据。

换句话说,显示该块

的下一个视图

我不知道你的代码是如何设置的,但这里有一个简单的例子(未经测试,所以不要复制粘贴)

假设我们有一个loginViewController让用户登录,然后是用户登录后主应用程序视图的mainViewController。

在AppDelegate中我们有

func showMainView() {

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

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

    self.mainVC.showWindow(self)

}

因此,在您的情况下,可以对块进行修改:

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

}})

因此,仅当Firebase有时间返回数据并填充变量时,才会显示主视图控制器。

答案 1 :(得分:0)

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

试试这个, 它可以帮助你。