J'ai un pour boucle contenant trois méthodes asynchrones et je tiens à faire un traitement après que ces 3 méthodes asynchronisées soient terminées.
-(void)getAllUsersInformations{ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ for(User *user in users){ [self getUserInfo:user]; } //Here, I want to reload the table view for example, after finishing the for loop (executing the whole three methods). }); } -(void)getUserInfo:(User*)user{ [self getInformations:user]; [self getExperiences:user]; [self getEducation:user]; }
4 Réponses :
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // Background work for(User *user in users){ [self getUserInfo:user]; } dispatch_async(dispatch_get_main_queue(), ^{ //reload tableview , this is on main thread. }); });
Les trois méthodes dans -GettuserInfo: code> sont asynchrones, qui ne vont pas que cela revienne tôt?
@Aarona. : Exactement Aaron.
Non, ces méthodes seront appelées synchroneusement sur fond. En effet, si vous mettrez un point d'arrêt sur la saisie du bloc, cela passera dessus. Lorsque la boucle pour la boucle sera terminée, le bloc DisPatch_ASync (DisPatch_Get_Main_Quue (), ^ {// Recharger la tableView, ceci est sur le fil principal.}); Code> sera appelé sur le fil principal. Faites un test rapide, cela devrait fonctionner.
@ADIPOP, les trois méthodes sont asynchrones, dans un bloc Dispatch_ASync. Le rechargement de la TableView sera exécuté avant la finition exécutant les 3 méthodes.
Essayez de faire un bloc avec l'achèvement, vous ne pouvez pas le faire avec une boucle si les méthodes sont asynchronisées. Vous devez appeler getuserinfo un par un après l'achèvement de la précédente. Je pense que cela va être résolu votre problème.
-(void)getAllUsersInformations{ [self registerUserAtIndex:0]; } - (void) registerUserAtIndex: (NSInteger ) userIndex { RegisterOperation *op = [[RegisterOperation alloc] initWithUser:[users objectAtIndex:userIndex]]; [RegisterOperation setResultCompletionBlock:^(BOOL *finished, NSInteger userIndex) { dispatch_async(dispatch_get_main_queue(), ^{ if (userIndex++ < [users count] { [self registerUserAtIndex:userIndex++]; } else { [myTableView reloadData]; } }]; [[NSOperationQueue mainQueue] addOperation:op]; }
Une approche GCD consiste à utiliser si Dispatch_group code>. Donc, avant de démarrer une tâche asynchrone, appelez
DisPatch_group_enter code>, puis lorsque la tâche asynchrone se termine, appelez
DisPatch_group_leave code>, et vous pouvez ensuite créer un
DisPatch_group_notify code > Qui sera appelé lorsque les tâches asynchrones finissent. Vous pouvez épouser cela avec un modèle de bloc d'achèvement (qui est une bonne idée pour les méthodes asynchrones, de toute façon):
getInformations code>,
getExperiences code> et
getEducation code> sont, eux-mêmes, toutes les méthodes asynchrones, la première chose dont vous avez besoin est un mécanisme pour savoir quand ils sont terminés. Une solution commune consiste à mettre en œuvre un modèle de bloc d'achèvement pour chacun. Par exemple: p>
// call new getUserInfo, using dispatch group to keep track of whether
// all the requests are done
-(void)getAllUsersInformations {
dispatch_group_t group = dispatch_group_create();
for(User *user in users){
dispatch_group_enter(group);
[self getUserInfo:user completionHandler:^{
dispatch_group_leave(group);
}];
}
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}
Quelle explication! Compris la technique, et je vais essayer de le mettre en œuvre. Je laisserai un retour d'information;).
Le dernier group_notify code> qui rechargne la vision de la table n'est jamais appelé. Je ne sais pas pourquoi, surtout comme le code> group_leave code> de
getuserinfo code> est appelé.
Tout d'abord, assurez-vous que le groupe final notify n'a pas été appelé (et que ce n'est pas simplement un problème que la recharge de la table n'a pas fonctionné correctement). Deuxièmement, pour diagnostiquer ceci, connectez-vous dans le groupe Entrer et congé dans GetAllUserSinformations CODE> et assurez-vous qu'ils Tous i> ont été appelés.
Merci beaucoup voler, ça fonctionne comme je voulais. Merci aussi pour les pensées finales, les 2) - Je l'ai déjà à l'esprit et pour le premier, je dois lire le Doc et peut-être le changer comme vous avez conseillé. Merci :) ...
ROP Réponse avec func processData()
{
let group: dispatch_group_t = dispatch_group_create()
for item in data as! Object {
dispatch_group_enter(group)
item.process(completion: {() -> (Void) in
dispatch_group_leave(group)
})
}
dispatch_group_notify(group, dispatch_get_main_queue(), {
//Do whatever you want
})
}
Sont
getinformations code>,
getExperiences code> et
getEducation code>, eux-mêmes, méthodes asynchrones? Ou sont-ils toutes des méthodes synchrones que vous expédieriez de manière asynchrone à une file d'attente de fond? (Votre édition à la question change radicalement la réponse.)
@Rob ; Oui, ils sont asynchrones!
GetAlluSersInformations Code>
GetInformations CODE>
GetExperiences code> et
GetEducation code> est asynchrone.
@androniennn pouvez-vous faire les trois
-getxxx code> méthodes synchrones?
@Aarona. Non, ce n'est pas possible, ils doivent être asynchronisés.