如何在viewDidLoad()函数上正确读取Firebase数据库?

时间:2017-08-16 12:31:15

标签: swift firebase firebase-realtime-database

//Just a struct to save information about the User
var user = AppUser()

override func viewDidLoad() {
    super.viewDidLoad()

 //Verify if user is logged in
    verifyUser()
    user.email = "blabla"

    print("viewdidload user: \(user)")

}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(true)

    print("viewdidappear user: \(user)")

} 

func verifyUser() {

    print("verify user called")

    //Log in verification
    guard let userID = Auth.auth().currentUser?.uid else {
        perform(#selector(handleLogOut), with: nil, afterDelay: 0)

        print("nil user")

        return
    }

    ref.child("users").child(userID).observeSingleEvent(of: .value, with: { (snapshot) in
        if let dictionary = snapshot.value as? [String: AnyObject] {
            self.user = AppUser(dictionary: dictionary)

            print(self.user)
        }
    }) { (error) in
        print(error.localizedDescription)
    }
}

控制台:

 verify user called


 viewdidload user: AppUser(id: nil, name: nil, email: 
 Optional("blabla"), completedRegister: nil, FULLUser: nil)


 viewdidappear user: AppUser(id: nil, name: nil, email:                
 Optional("blabla"), completedRegister: nil, FULLUser: nil)


 AppUser(id: nil, name: nil, email: Optional("x@gmail.com"),      
 completedRegister: Optional(false), FULLUser: Optional(false))

问题很简单。有人可以解释在“验证用户呼叫”和“用户”与数据库信息之间打印"print("viewDidLoad user:....")"怎么可能?

问题是当我尝试在viewDidLoad上获取用户的信息时,由于某种原因,该函数没有获取信息,因此值仍为零。这是时间问题吗?

我试图在函数verifyUser()之后放置一个循环,但它永远不会得到

out:

    while user.email == nil {
            print("Waiting...")
        }

所以......那就是问题

谢谢!

编辑Anas Menhar 这是我的结构。为什么成为NSObject会更好? 我做了一个Struct,因为我可以做两个不同的inits(一个空),而且NsObject没有让我出于某种原因

struct AppUser {
var id: String?
var name: String?
var email: String?

var completedRegister: Bool?

var FULLUser: Bool?

init(dictionary: [String: Any]) {
    self.id = dictionary["id"] as? String
    self.name = dictionary["name"] as? String
    self.email = dictionary["email"] as? String

    self.completedRegister = Bool((dictionary["completedRegister"] as? String)!)

    self.FULLUser = Bool((dictionary["FULLUser"] as? String)!)

}
init() {
    self.id = nil
    self.name = nil
    self.email = nil

    self.completedRegister = nil

    self.FULLUser = nil

}
}

编辑Hitesh

如果我打印字典,它就会在用户完成信息的同时打印。一切都结束了。

1 个答案:

答案 0 :(得分:1)

问题是viewDidLoad()在打印verifyUser()之前调用"viewdidload user: \(user)"verifyUser()中的所有内容都将在打印前完成(网络电话除外)。

所以这是发生在你身上的一系列事件:

  1. super.viewDidLoad()
  2. verifyUser()被称为
  3. verifyUser()
  4. 中的print语句
  5. verifyUser()
  6. 中的保护声明
  7. viewDidLoad()
  8. 中打印声明
  9. super.viewDidAppear()
  10. 打印在super.viewDidAppear()
  11. .observeSingleEventOf闭包内的所有内容都将在4之后的某个时刻发生 - 每当调用完成时。如果你想在完成调用时做某事,可以把它放在闭包中。

    像这样:

     ref.child("users").child(userID).observeSingleEvent(of: .value, with: { (snapshot) in
        if let dictionary = snapshot.value as? [String: AnyObject] {
            self.user = AppUser(dictionary: dictionary)
            //***handle stuff that needs the user here
            print(self.user)
        } else {
            //***handle getting no data for the user or data that is not [String: AnyObject]
        }
    }) { (error) in
        //***handle any errors here
        print(error.localizedDescription)
    }
    

    我添加注释的地方是该请求完成时可能会被调用的地方。

    附注:如果您打算使用Struct for AppUser,只需确保您知道结构和类之间的差异。你可以有一个名为AppUser的类,它有两个不同的命令:

    class AppUser {
        var id: String?
        var name: String?
        var email: String?
        var completedRegister: Bool?
        var FULLUser: Bool?
    
        ///initialization from a dictionary
        init(dictionary: [String: Any]) {
            id = dictionary["id"] as? String
            name = dictionary["name"] as? String
            email = dictionary["email"] as? String
    
            if let completed = dictionary["completedRegister"] as? String {
                if completed == "true" {
                    completedRegister = true
                } else if completed == "false" {
                    completedRegister = false
                }
            }
    
            if let fullUser = dictionary["FULLUser"] as? String {
                if fullUser == "true" {
                    FULLUser = true
                } else if fullUser == "false" {
                    FULLUser = false
                }
            }
        }
    
        ///initialization without a dictionary
        init() {
            //dont need to set any variables because they are optional
        }
     }
    
    let user1 = AppUser(dictionary: ["id": "12342",
                                 "name": "John Doe",
                                 "email": "email@email.com",
                                 "completedRegister": "true",
                                 "FULLUser": "true"])
        ///user1 properties:
        id: Optional("12342")
        - some: "12342"
        name: Optional("John Doe")
        - some: "John Doe"
        email: Optional("email@email.com")
        - some: "email@email.com"
        completedRegister: Optional(true)
        - some: true
        FULLUser: Optional(true)
        - some: true
    
    let user2 = AppUser()
    ///user2 properties: none