所以这是我的Firebase结构:
我试图获取所有图书图片(bookImage),将它们添加到列表中,然后使用此列表填充表格或其他任何内容。 (我使用swift 3)
struct item {
let picture: String!}
var items = [item]()
func getLatestAddedItems(){
let databaseRef = FIRDatabase.database().reference()
databaseRef.child("Items").observe(.childAdded, with: {
FIRDataSnapshot in
let picture = (FIRDataSnapshot.value as? NSDictionary)?["bookImage"] as? String ?? ""
//self.items.insert(item(picture: picture), at: 0)
self.items.append(item(picture: picture))
print(self.items[0].picture)
print(self.items[1].picture) // error here
})}
我能够看到第一个打印输出,但是在第二个打印输出中我得到致命错误:索引超出范围,即使我的数据库中有3本书。
答案 0 :(得分:2)
最后,我发布了解决方案:
func getLatestAddedItems(){
let databaseRef = FIRDatabase.database().reference()
databaseRef.child("Items").observe(.value, with: {
snapshot in
//self.items.insert(item(picture: picture), at: 0)
for childSnap in snapshot.children.allObjects {
let snap = childSnap as! FIRDataSnapshot
print(snap.key)
let picture = (snap.value as? NSDictionary)?["bookImage"] as? String ?? ""
print(picture)
}
})
}
答案 1 :(得分:1)
由于您使用.childAdded,它会遍历数据树中每个对象的闭包,在本例中为每本书。当您尝试打印第二张图片时,它仍处于第一次迭代中。这意味着到目前为止您只检索了第一本书。这就是为什么你可以打印第一本书而不是第二本书。如果你将print语句移到闭包之外,然后在闭包迭代完所有三本书之后做了print语句,你就不会得到错误。
不要将其更改为.value,除非每次添加新的时候都要重新获得整个书籍列表。如果它有大量的书籍,那么每次都会有大量的数据。
摘要:.childAdded一次为您提供一本书,每本书都有一个新的快照。 .value在一个快照中为您提供所有书籍,然后您必须在闭包中自己迭代它们。恩。
for snap in snapshot.children {
// now you can do something with each individual item
}
我也注意到你在闭包中使用了FIRDataSnapshot类型,它应该是一个代表你收到的快照的变量,而不是类型本身。将“FIRDataSnapshot in”更改为“snapshot in”快照,表示观察闭包给出了哪些信息,在本例中是一个FIRDataSnapshot类型的对象。
编辑:
您在下面提到的解决方案运行正常,但我会添加一个更干净,更易于使用的替代方案。
将一个init方法添加到Book类中,该方法将FIRDataSnapshot作为init参数,然后在查询Firebase时初始化该对象:
struct Book {
let bookImageString: String
init?(snapshot: FIRDataSnapshot) {
guard let snap = snapshot.value as? [String : AnyObject], let urlString = snap["bookImage"] else { return nil }
bookImageString = imageString
{
{
然后当你查询firebase时,你可以这样做:
for snap in snapshot.children {
if let snap = snap as? FIRDataSnapshot, let book = Book(snapshot: snap) {
self.items.append(book)
{
}
这样做可以清理代码并减少代码中出错的可能性。
此外,由于您使用.value,请确保在关闭的开头清空数据源数组,否则在添加新书时会出现重复。
items.removeAll()