通过在iOS中加入表格从Firebase提取数据
我试图从两个不同的Firebase表格中提取数据。下面是表的结构:我需要检索相应的发布与ID = 1。以下是我实施检索图像图像通过在iOS中加入表格从Firebase提取数据
Post {
1{
pImages{
i1:true
i2:true
}
}
2{
pImages{
i3:true
}
}
}
Images{
i1{
iUrl : ....
pId : 1
}
i2{
iUrl :...
pId : 1
}
i3{
iUrl:....
pId : 2
}
}
:
func retrieveImagesForPost(postId: String,completion: (result: AnyObject?, error: NSError?)->()){
var imgArray:[Image]=[]
let postsRef = self.ref.child("post")
let imagesRef = self.ref.child("image")
let postImagesRef = postsRef.child(postId).child("pImages");
postImagesRef.observeEventType(FIRDataEventType.Value, withBlock: { (snapshot) in
for item in snapshot.children{
imagesRef.child(item.key).observeSingleEventOfType(.Value, withBlock: { (snap) in
let image = Image(snapshot: snap)
print(image)
imgArray.append(image)
})
}
print(snapshot.key)
print("called")
completion(result:imgArray, error:nil)
})
}
但是,问题是我无法将imgArray
中的所有图像发送至completion handler
。以下是调用retrieveImagesForPost
后的输出id = 1。
pImages
called
<TestProject.Image: 0x7f9551e82000>
<TestProject.Image: 0x7f955466a150>
在调用completion handler
后检索图像。我尝试了dispatch groups
和semaphores
方法,如下面的post所述。但结果仍然相同。我如何让completion handler
等待所有图像从Firebase中获取?
保留一个随着每个图像加载而增加的计数器。一旦计数器达到snapshot.children
列表的长度,就完成并调用完成处理程序。
let postImagesRef = postsRef.child(postId).child("pImages");
postImagesRef.observeEventType(FIRDataEventType.Value, withBlock: { (snapshot) in
var counter = 0
for item in snapshot.children{
imagesRef.child(item.key).observeSingleEventOfType(.Value, withBlock: { (snap) in
let image = Image(snapshot: snap)
print(image)
imgArray.append(image)
counter = counter + 1
if (counter == snapshot.childrenCount) {
completion(result:imgArray, error:nil)
}
})
}
})
您应该在上面添加一些错误处理,但通常这种方法已经过尝试和测试。
此问题的另一个答案是使用GCD的DispatchGroup
。
首先,您需要创建一个包含DispatchGroup
的调度组。在这种情况下,您需要通过enter()
以及leave()
完成工作时手动通知组。然后调度组的notify(queue:execute:)
将在主队列上执行完成处理程序。
小心!进入和离开的数量必须平衡,否则调度组的通知将永远不会被调用。
let dispatchGroup = DispatchGroup()
let postImagesRef = postsRef.child(postId).child("pImages");
postImagesRef.observeEventType(FIRDataEventType.value, withBlock: { (snapshot) in
for item in snapshot.children{
dispatchGroup.enter()
imagesRef.child(item.key).observeSingleEventOfType(.value, withBlock: { (snap) in
let image = Image(snapshot: snap)
print(image)
imgArray.append(image)
dispatchGroup.leave()
})
}
})
dispatchGroup.notify(queue: DispatchQueue.main, execute: {
completion(result: imgArray)
})
这比使用计数器好得多,就像在公认的答案中一样。尽管为了正常工作,'dispatchGroup'必须在第一个观察块内实例化,并在'for'之后通知。进入和离开组是正确的。 –
请问你的功能变化,我会需要火力地堡 – Learn2Code
加入3个节点(关系),如果(反== snapshot.childrenCount)抛出一个错误!? – Learn2Code