2016-07-10 32 views
3

我試圖從兩個不同的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 groupssemaphores方法,如下面的post所述。但結果仍然相同。我如何讓completion handler等待所有圖像從Firebase中獲取?

回答

4

保留一個隨着每個圖像加載而增加的計數器。一旦計數器達到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) 
      } 
     }) 
    } 
}) 

您應該在上面添加一些錯誤處理,但通常這種方法已經過嘗試和測試。

+0

請問你的功能變化,我會需要火力地堡 – Learn2Code

+0

加入3個節點(關係),如果(反== snapshot.childrenCount)拋出一個錯誤!? – Learn2Code

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) 
}) 
+0

這比使用計數器好得多,就像在公認的答案中一樣。儘管爲了正常工作,'dispatchGroup'必須在第一個觀察塊內實例化,並在'for'之後通知。進入和離開組是正確的。 –

相關問題