2

특정 노드가 존재하면 Firebase 데이터베이스에서 확인하려고하고, 그렇지 않으면 데이터베이스에 새로운 노드를 작성하려고합니다. 누락 된 노드를 만드는 두 번째 메서드를 호출하기 전에 내 메서드 loadAll()을 완전히 실행해야합니다. autoCheck. 이 작업을 수행 할 디스패치 그룹을 시도했지만 작동하지 않습니다, print("Done downloading!") 데이터베이스가 검사 완료되기 전에 호출됩니다. 감사!!GCD가 블록 순서로 실행되지 않음

코드 :

func loadAll(){ 
    var deleted_load = false 
    var poor_load = false 
    var allLoadDone = false 

    if let user = FIRAuth.auth()?.currentUser { 
     let uid = user.uid 

     let refff = FIRDatabase.database().reference() 
     let userRef = refff.childByAppendingPath("users/\(uid)") 


     //When making new fields increase this var 
     var howmany = 2 
     var done = 0 

     var downloadGroup = dispatch_group_create() 
     dispatch_group_enter(downloadGroup) 
     userRef.queryOrderedByValue().observeEventType(.ChildAdded, withBlock: { snapshot in 
      allLoadDone = true 
      if(!snapshot.exists()){ 
       print("ERR DOES NOT EXCIST") 
       self.autoCheck(deleted_load, poor_load: poor_load, userRef: userRef, ig: 1) 
       return 
      } 
      if let score = snapshot.value as? Int { 
       if(snapshot.key=="deleted"){ 
        deleted_load = true 
       } 
       if(snapshot.key=="Staff_Poor"){ 
        poor_load = true 
       } 
       print("\(snapshot.key) is \(score)") 
       self.counter.text = String(score) 
      } 
      done = done + 1 
      if(done>=(howmany)){ 
       self.autoCheck(deleted_load, poor_load: poor_load, userRef: userRef, ig: 2) 
      } 
     }) 
      dispatch_group_leave(downloadGroup) 

     dispatch_group_notify(downloadGroup, dispatch_get_main_queue()) { // 2 
      print("Done downloading!") 
     } 
    } else { 
     print("No user!") 
     gotoLogin() 
    } 
} 

func autoCheck(deleted_load: Bool, poor_load: Bool, userRef: FIRDatabaseReference, ig: Int) -> Bool{ 
    print("ID IS: \(ig)") 
    var newUserData = ["deleted": 0, "Staff_Poor": 0] 
    print("deleted_load: \(deleted_load)") 
    if deleted_load==true{ 
     newUserData.removeValueForKey("deleted") 
    } 
    print("poor_load: \(poor_load)") 
    if poor_load==true{ 
     newUserData.removeValueForKey("Staff_Poor") 
    } 
    if(!newUserData.isEmpty){ 
     userRef.updateChildValues(newUserData) 
    } 

    return true 
} 

답변

3

dispatch_group_leave(downloadGroup)에 대한 귀하의 호출이 완료 핸들러 폐쇄 내부에 배치해야합니다. 지금은 비공개 호출이 완료되기 전에 그룹이 완료된다는 것을 의미합니다.

하지만 단계별로 살펴보고 파견 그룹의 목적을 이해합시다. 일반적인 패턴은 전체 일련의 비동기 작업을 수행 할 때 디스패치 그룹을 사용하고 모든 작업이 완료된 시점을 알고 싶습니다. 발송 그룹의

let group = dispatch_group_create() 

for object in arrayOfObjects { 
    dispatch_group_enter(group) 
    performSomeAsynchronousActionWithObject(object) { result in 
     // do something with `result` 
     ... 
     dispatch_group_leave(group) 
    } 
} 

dispatch_group_notify(group, dispatch_get_main_queue()) { 
    print("done performing asynchronous task with all of those objects") 
} 

솔직히, 사용 : 같은 것을 그래서, 각 작업, 당신은 몇 가지 비동기 프로세스를 호출하기 전에 그룹을 입력 한 다음 해당 비동기 프로세스의 완료 핸들러 내 카페에서 탈퇴 여기에 적합하지 않을 수 있습니다. 모든 "입력"이 해당 "휴가"와 일치하는 파견 그룹 개념. 당신은 한 번 "enter"라고 부르지 만, 관찰자가 궁극적으로 몇 번이나 불려지는지 확신 할 수는 없습니다.

그러나이 경우 이벤트가 여러 번 발생하지만 코드의 일부 블록이 호출되는 "관찰자"를 상대하게됩니다. 그것은 전혀 일어나지 않을 수도 있습니다. 그것은 여러 번 일어날 수 있습니다. 관찰 된 사건이 ​​몇 번이나 일어 났는지에 대한 질문 일뿐입니다.

이제 한 번만 호출된다는 것을 확실하게 알게되면 기술적으로이 패턴이 작동합니다. 그러나 단 한 번 전화가 오면, 당신은 파견단이 전혀 필요하지 않습니다.

+0

안녕하세요 사용자가 내 데이터베이스에 있지 않은 경우 (새 사용자 인 경우) 다른 이유로 'userRef.queryOrderedByValue(). observeEventType (.ChildAdded, withBlock : {snapshot in' does 어떤 것이 잘못되었거나 Firebase의 작동 방식이 무엇입니까? – ZachtheBoB

+0

저는 Firebase의 전문가는 아니지만 관찰자 패턴을 사용하면 일반적으로 클로저가 여러 번 호출되어'.ChildAdded' 이벤트가 트리거됩니다. – Rob

+0

'.ChildAdded' 이벤트가 한 번 발생했습니다. 내 데이터베이스에'users/ '이 있고 앱이'users/'이 제거 된 앱을 두 번 실행했습니다. 'users/ '이 있으면'.ChildAdded' 이벤트가 발생했지만 두 번째로 그것은 방아쇠를 당길 수 없었다. @rob – ZachtheBoB