[英]How to know which initializer to use for reading data(Firebase)
我有兩個初始化程序:
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
]
}
}
為了讀取最新數據,我將此方法與 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)
}
為什么以及何時需要使用第二個 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()
但是我的方法與第一個初始化相同。
問題實際上是在詢問功能上相同的兩件事。
在一種情況下,快照被“分解”為 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...
然后將該原始數據傳遞給結構。 然后將 object 添加到數組中
在第二種情況下,快照本身被傳遞給結構
init?(snapshot:DataSnapshot) {
guard let value = snapshot.value as? [String:AnyObject],
快照被分解為 object 中的原始數據。
兩者 function 相同。
這是可讀性和個人喜好的問題。 一般來說,在 object 中包含初始化程序等可以使代碼更具可讀性,object 更可重用且代碼更少 - 請參閱此偽代碼
DataObjects.infoRef.child(uid!).observe(.value){ snapshot, error in
let user = UserInfo(snapshot)
self.newArray.append(user)
})
這是非常緊湊的代碼。
想象一下,如果您想在應用程序中訪問這些對象的 10 個地方。 在您的第一種情況下,該代碼必須復制 10 次——這可能需要更多的故障排除。 在我上面的示例中,object 本身完成了繁重的工作,因此訪問它們需要的代碼要少得多。
另外兩件事。 您可能需要考慮使用 .childSnapshot 來訪問快照而不是字典中的數據(無論哪種方式都有效)
let userName = snapshot.childSnapshot(forPath: "name").value as? String ?? "No Name"
請避免強制展開可選變量
child(uid!)
因為它會導致不穩定的代碼和隨機的、無法解釋的崩潰。 這會更好
guard let uid = maybeUid else { return } //or handle the error
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.