通过在iOS中连接表来从Firebase获取数据

时间:2016-07-10 02:55:23

标签: ios firebase firebase-realtime-database completionhandler

我正在尝试从两个不同的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
         }
 }

我需要检索与id = 1的post相对应的图像。以下是我检索图像的实现:

 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。以下是使用帖子ID == 1来调用retrieveImagesForPost的输出。

pImages
called
<TestProject.Image: 0x7f9551e82000>
<TestProject.Image: 0x7f955466a150>

在调用completion handler后检索图像。我按照以下post中的说明尝试了dispatch groupssemaphores方法。但结果仍然相同。如何让completion handler等待从Firebase获取所有图片?

2 个答案:

答案 0 :(得分:5)

保留一个计数器,在每个图像加载时增加。一旦计数器达到=IF(D9 = ”Imperial”, IF(D10 = ”Male”, M8, M10), IF(D10 = ”Male”, M7, M9) ) 列表的长度,您就完成了并调用完成处理程序。

snapshot.children

您应该在上面添加一些错误处理,但一般来说,这种方法都经过了尝试和测试。

答案 1 :(得分:1)

此问题的另一个答案是使用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)
})