2017-09-07 1 views
0

Je sais qu'il y a déjà beaucoup de contributions pour ce sujet. J'ai essayé différentes variations avec DispatchGroup, mais il semble que je ne suis pas capable de faire toute la boucle jusqu'à ce qu'une certaine tâche soit terminée.Comment faire une boucle attendre jusqu'à ce que la tâche est terminée

let names = ["peter", "susan", "john", "peter", "susan", "john"] 
var holding = [String: [Double]]() 


for i in 0...10 { 

    for name in names { 

     if holding[name] == nil { 
      Alamofire.request("https://jsonplaceholder.typicode.com", parameters: parameters).responseJSON { responseData in 

        // do stuff here 
        holding[name] = result 
      } 

     } else { 
      // do other stuff with existing "holding[name]" 

     } 

     // if if holding[name] == nil, the whole process should wait 
    } 
} 

Si je suis en utilisant DispatchGroup, les demandes Alamofire sont exécutées une par une, mais la boucle entière ne reconnaît pas si holding[name] existe déjà. Donc holding[name] est toujours nil car la boucle n'attend pas.

Merci beaucoup!

EDIT:

Selon les réponses Mikes's et Versus', j'ai essayé les éléments suivants:

var names = ["peter", "susan", "john", "peter", "susan", "john"] 
var holding = [String: [Double]]() 

let semaphore = DispatchSemaphore(value: 1) 

for i in 0...10 { 

    DispatchQueue.global().async { [unowned self] in 
     self.semaphore.wait() 

     for name in names { 

      if holding[name] != nil { 
       Alamofire.request("https://jsonplaceholder.typicode.com", parameters: parameters).responseJSON { responseData in 

        // do stuff here 
        holding[name] = result 
        semaphore.signal() 
       } 

      } else { 
       // do other stuff with existing "holding[name]" 
       semaphore.signal() 

      } 

      // if if holding[name] != nil, the wholeprocess should wait 
     } 
    } 
} 

Mais malheureusement, les accidents d'applications. Qu'est-ce que je fais mal?

+0

Est [cette question] (https: // stackoverflow.com/questions/41809000/call-completion-block-when-two-other-completion-blocks-have-been-called) liés à votre problème? –

+0

Où l'application se bloque et quel est le journal? –

+0

Ceci est le plus facile: [image] (http://imgur.com/a/6zZTL) –

Répondre

1

Vous avez deux choix ici

1) Semaphore

2) Operation Queues

Mais vous devriez réfléchir à deux fois avant de partir avec Semaphores

vous devez être prudent sur semaphore.signal() et semaphore.wait() paire

Comme Semaphore peut bloquer thread principal donc toutes les opérations doivent se faire dans Dispatch.global.async

-à-dire

semaphore.wait() 

Alamofire.request("https://jsonplaceholder.typicode.com", parameters: parameters).responseJSON { responseData in 

        semaphore.signal() 
        holding[name] = result 

} 

Vous êtes bloc le fil principal

Le problème est que le gestionnaire d'achèvement est exécuté dans le thread principal, qui était déjà verrouillé par le semaphore.wait() appelé initialement. Ainsi, lorsque l'achèvement se produit, semaphore.signal() ne sera jamais appelé

Vous devez aller avec

DispatchQueue.global().async { [unowned self] in 
     self.semaphore.wait() 
     // And other statemetns 

    } 

L'espoir, il est utile de vous et d'autres

+0

Merci cela ressemble à la bonne façon. J'ai fait j'essaye avec ta suggestion. Mais l'application se bloque. Qu'est-ce que je fais mal? Voir mise à jour. –

1

Je pense que vous pouvez utiliser DispatchSemaphore pour arrêter la boucle:

let semaphore = DispatchSemaphore(value: 1) 
for i in 0...10 { 

    for name in names { 
     // if signal is 0, loop will be stopped forever, 
     // if signal > 0, loop will continue 
     semaphore.wait() 
     if holding[name] == nil { 
     Alamofire.request("https://jsonplaceholder.typicode.com", parameters: parameters).responseJSON { responseData in 

       // do stuff here 
       // release signal to continue current loop(signal + 1) 
       semaphore.signal() 
       holding[name] = result 
      } 

     } else { 
     // do other stuff with existing "holding[name]" 

     } 

    // if if holding[name] == nil, the whole process should wait 
    } 
} 
+0

Je viens d'essayer. Malheureusement, ça ne fait pas la boucle d'attendre. –