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") 
} 

Честно говоря, использование отправки группы может оказаться неприемлемым. Понятие с диспетчерскими группами о том, что каждый «ввод» соответствует соответствующему «отпуску». Вы вызываете «вводить» один раз, но неясно, что у вас есть какие-то заверения в том, сколько раз наблюдатель будет в конечном итоге вызван.

Но в этом случае вы имеете дело с «наблюдателем», некоторым блоком кода, который будет вызываться, однако много раз происходит событие. Это может не произойти вообще. Это может происходить много раз. Это всего лишь вопрос о том, сколько раз наблюдаемое событие имеет место.

Теперь, если вы с уверенностью знаете, что это будет называться один раз и только один раз, тогда технически этот шаблон будет работать. Но если его вызывают один раз и только один раз, вам действительно не нужна диспетчерская группа.

+0

У меня есть другой вопрос, по какой-либо причине, если пользователь не находится в моей базе данных (например, если это новый пользователь) 'userRef.queryOrderedByValue(). ObservEventType (.ChildAdded, withBlock: {snapshot in' does не выполняю.Я делаю что-то не так, или это то, как работает Firebase? – ZachtheBoB

+0

Я не эксперт в Firebase, но с шаблоном наблюдателя это закрытие обычно вызывает так много раз, что срабатывает событие '.ChildAdded'. Уверен, что сколько раз это событие было вызвано? – Rob

+0

Событие '.ChildAdded' запускается один раз. Я запускал приложение дважды, один раз с' users/ ', существующим в моей базе данных, и один раз с' users/ 'удален из моей базы данных. С 'users/' существующим было инициировано событие '.ChildAdded', однако второй раз он не смог вызвать. @Rob – ZachtheBoB

Смежные вопросы