2017-08-16 53 views
0
//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) 
    } 
} 

控制台:如何正确读取viewDidLoad()func上的Firebase数据库?

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("[email protected]"),  
completedRegister: Optional(false), FULLUser: Optional(false)) 

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

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

我试图把一个循环功能verifyUser()之后,但它从来没有得到

out: 

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

所以......这就是问题

谢谢!

编辑阿纳斯·门哈尔 这是我的结构。为什么做一个NSObject会更好? 我做了一个结构,因为我可以做两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 

} 
} 

编辑为亚太区首席技术官Matt

,如果我打印出来只是在打印字典用户完成信息的同时。在一切结束。

+0

你有没有打印'让字典= snapshot.value'?你可以加这个吗? – Hitesh

+0

让我看看你的AppUser模态类,它必须像类一样用户:NSObject {var_id:String? var name:String? var email:String? var imageURL:String? }并且也使用这一行 user.setValuesForKeys(dictionary) –

回答

1

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

所以这里是事件发生的对你的序列:

  1. super.viewDidLoad()
  2. verifyUser()
  3. 打印语句是verifyUser()
  4. 后卫声明是verifyUser()
  5. 打印在viewDidLoad()的说明
  6. 每当通话结束 -
  7. 打印在封闭的.observeSingleEventOf内super.viewDidAppear()

一切都将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) 
} 

,我添加了注释是请求完成时将可能被称为地方的地方。

附注:如果你要使用APPUSER一个结构,只是确保你知道结构和类之间的差异。你可以有一个名为APPUSER类,有两个不同的inits这样的:

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 protected]", 
          "completedRegister": "true", 
          "FULLUser": "true"]) 
    ///user1 properties: 
    id: Optional("12342") 
    - some: "12342" 
    name: Optional("John Doe") 
    - some: "John Doe" 
    email: Optional("[email protected]") 
    - some: "[email protected]" 
    completedRegister: Optional(true) 
    - some: true 
    FULLUser: Optional(true) 
    - some: true 

let user2 = AppUser() 
///user2 properties: none 
+0

哪个是类的优点?是不是结构是值类型和类是引用类型的主要区别?所以在我的情况下,结构会更好地完成这项工作吗?最后一件事,为什么网络内容会在viewDidLoad代码的其余部分之后出现?谢谢!! – Alexis

+0

是的。随着功能的扩展,类作为引用类型使得它们稍后更具动态性。网络通话按您写入的顺序开始,但不一定按照该顺序完成。想象一下,你正在下载一张10MB的高分辨率照片和500kb的低分辨率照片。您可以按任意顺序启动它们,但(除非它们同步运行)500kb可能会先完成。 – erdos