2016-07-10 2 views
3

두 개의 다른 Firebase 테이블에서 데이터를 가져 오려고합니다.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 
     } 
} 

내가 ID로 이미지를 검색 할 수 = 1되어 다음 내 구현 게시에 해당하는 이미지 검색해야 : 여기에 테이블의 구조

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에서 모든 이미지를 가져올 때까지 기다리는 방법은 무엇입니까?

답변

4

각 이미지가로드 될 때마다 증가하는 카운터를 유지하십시오. 카운터가 snapshot.children 목록의 길이에 도달하면 작업이 완료되고 완료 핸들러를 호출합니다.

위의 경우 오류 처리를 추가해야하지만 일반적으로이 방법을 시도하고 테스트합니다.

+0

!? – Learn2Code

+0

3 개 노드 (관계)에 가입하기 위해 기능을 변경해야 않는 방법 – 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) 
}) 
내가 (카운터 == snapshot.childrenCount가)에서 오류가 발생하는 경우 중포 기지
+0

이것은 허용 된 대답에서와 같이 카운터를 사용하는 것보다 훨씬 낫습니다. 그것이 제대로 작동하기 위해서는 'dispatchGroup'이 첫 번째 관찰 블록 내부에서 인스턴스화되어야하고 'for'다음에 통지되어야합니다. 그룹에 들어가거나 나가는 것이 정확합니다. –

관련 문제