简体   繁体   English

如何知道使用哪个初始化程序来读取数据(Firebase)

[英]How to know which initializer to use for reading data(Firebase)

I've got two initializers:我有两个初始化程序:

    struct UserInfo{
let ref: DatabaseReference?
let key: String
let firstName: String
let lastName: String
let username: String
let pictureURL : String?
let admin : Bool

init(firstName: String, lastName:String,username:String,pictureURL:String?,admin:Bool, key:String = "" ){
    self.ref = nil
    self.key = key
    self.firstName = firstName
    self.lastName = lastName
    self.username = username
    self.pictureURL = pictureURL
    self.admin = admin
    
}

init?(snapshot:DataSnapshot){
    guard let value = snapshot.value as? [String:AnyObject],
          let firstName = value["firstName"] as? String,
          let lastName = value["lastName"] as? String,
          let username = value["userName"] as? String,
          let profilePic = value["pictureURL"] as? String,
          let admin = value["isAdmin"] as? Bool
            
    else {return nil}

    self.ref = snapshot.ref
    self.key = snapshot.key
    self.firstName = firstName
    self.lastName = lastName
    self.username = username
    self.pictureURL = profilePic
    self.admin = admin
}
func toAnyObject()-> Any{
    return [
        "firstName": firstName,
        "lastName": lastName,
        "username": username,
        "pictureURL":pictureURL as Any,
        "isAdmin": admin
    ]
}

} }

For reading most recent data I use this method combined with first init and it works:为了读取最新数据,我将此方法与 first init 结合使用,它可以工作:

   let completed =
    DataObjects.infoRef.child(uid!).observe(.value){ snapshot,error in
        var newArray: [UserInfo] = []
            if let dictionary = snapshot.value as? [String:Any]{
                let username = dictionary["username"] as! String
                let firstName = dictionary["firstName"] as! String
                let lastName = dictionary["lastName"] as! String
                let profilePic = dictionary["pictureURL"] as? String
                let admin = dictionary["isAdmin"] as! Bool
                let userInformation = UserInfo(firstName: firstName, lastName: 
           lastName, username: username,pictureURL: profilePic, admin: admin)
                newArray.append(userInformation)
                print(newArray)
                completion(.success(newArray))
                print(newArray)
            }

Why and when do I need to use second init??为什么以及何时需要使用第二个 init?

In Firebase tutorial on raywenderlich.com we gat example about: Synchronizing Data to the Table View using second init:在有关 raywenderlich.com 的 Firebase 教程中,我们了解了以下示例:使用第二个 init 将数据同步到表视图:

    let completed = ref.observe(.value) { snapshot in
 // 2
 var newItems: [GroceryItem] = []
 // 3
 for child in snapshot.children {
  // 4
  if
  let snapshot = child as? DataSnapshot,
  let groceryItem = GroceryItem(snapshot: snapshot) {
  newItems.append(groceryItem)
 }
}
 // 5
 self.items = newItems
 self.tableView.reloadData()

But my method works the same with first init.但是我的方法与第一个初始化相同。

The question is really asking about two things that functionally work the same.问题实际上是在询问功能上相同的两件事。

In one case the snapshot is being "broken down" into its raw data (strings etc) within the firebase closure在一种情况下,快照被“分解”为 firebase 闭包中的原始数据(字符串等)

   DataObjects.infoRef.child(uid!).observe(.value){ snapshot,error in
      let username = dictionary["username"] as! String
      let firstName = dictionary["firstName"] as! String
      let lastName = dictionary["lastName"] as! String
      let userInformation = UserInfo(firstName: firstName, lastName: lastName...

and then passing that raw data to the struct.然后将该原始数据传递给结构。 That object is then added to the array然后将 object 添加到数组中

In the second case the snapshot itself is passed to the struct在第二种情况下,快照本身被传递给结构

init?(snapshot:DataSnapshot) {
    guard let value = snapshot.value as? [String:AnyObject],

and the snapshot is broken down into it's raw data within the object.快照被分解为 object 中的原始数据。

The both function the same.两者 function 相同。

It's a matter of readability and personal preference.这是可读性和个人喜好的问题。 Generally speaking having initializers etc within an object can make the code a bit more readable, the object more reusable and less code - see this pseudo code一般来说,在 object 中包含初始化程序等可以使代码更具可读性,object 更可重用且代码更少 - 请参阅此伪代码

DataObjects.infoRef.child(uid!).observe(.value){ snapshot, error in
    let user = UserInfo(snapshot)
    self.newArray.append(user)
})

That's pretty tight code.这是非常紧凑的代码。

Imagine if there were 10 places you wanted to access those objects within your app.想象一下,如果您想在应用程序中访问这些对象的 10 个地方。 In your first case, that code would have to be replicated 10 times - which could be a lot more troubleshooting.在您的第一种情况下,该代码必须复制 10 次——这可能需要更多的故障排除。 In my example above, the object itself does the heavy lifting so accessing them requires far less code.在我上面的示例中,object 本身完成了繁重的工作,因此访问它们需要的代码要少得多。

Two other things.另外两件事。 You may want to consider using.childSnapshot to access the data within a snapshot instead of a dictionary (either way works)您可能需要考虑使用 .childSnapshot 来访问快照而不是字典中的数据(无论哪种方式都有效)

let userName = snapshot.childSnapshot(forPath: "name").value as? String ?? "No Name"

and please avoid force unwrapping optional vars请避免强制展开可选变量

child(uid!)

as it will cause unstable code and random, unexplained crashes.因为它会导致不稳定的代码和随机的、无法解释的崩溃。 This would be better这会更好

guard let uid = maybeUid else { return } //or handle the error

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

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