2

特定のノードが存在する場合、Firebaseデータベースからチェックしようとしています。存在しない場合は、データベースに新しいノードを作成します。私は、loadAll()というメソッドが、実行されていないノードを作成する2番目のメソッドを呼び出す前に実行する必要があります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 – ZachtheBoB

+0

私はFirebaseの専門家ではありませんが、オブザーバーのパターンでは、クロージャーは一般的には何度も呼び出されますが、 '.ChildAdded'イベントがトリガーされることは何度もあります。 – Rob

+0

'.ChildAdded'イベントが1回だけトリガされました。私はアプリケーションを' users/ 'をデータベースに2回、' users/ 'を削除して2回実行しました私のデータベースから 'users/'が存在すると、 '.ChildAdded'イベントがトリガされましたが、2回目トリガーに失敗しました。 @Rob – ZachtheBoB

関連する問題