Attente de completion block
Bonjour,
Je fais face à un problème pour la première fois, en effet le retour de ma méthode dépend d'une valeur modifiable dans le block, je vous donne l'exemple :
BOOL __block found = NO;
[bookings retrieveAllBookings:^(NSArray * bookings, NSError * error){
for (Reservation *resa in bookings) {
if ([(Reservation*)resa checkIn] ) {
found = YES;
}
}
}];
return found;
C'est quoi le moyen le plus approprié pour attendre la fin d'execution de ce Block pour retourner cette valeur.
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
1. Tu as une méthode nommé retrieveAllBookings mais tu ne les récupères pas ; en revanche, tu les fouilles.
2. Tu as dupliqué "bookings" une fois dans l'appel et la deuxième fois dans les paramètres.
3. Le cast vers Reservation sur chaque article de la liste ne sert à rien parce que le for..in ne passe que le Reservations.
Hello, merci pour la réponse,
retrieveAllBookings est une méthode qui fait appel à un web service. La variable bookings est un array retourné à partir de cette méthode là , du coup la solution des predicate n'est pas la plus approprié.
Je reviens sur ma question initial, c'est comment attendre le block qu'il finisse ?
merci
Mais de toute façon, je pense qu'il n'est pas approprié d'attendre, car si ton code est appelé dans le thread principal, alors cela résultera en des blocages de l'interface graphique, et c'est mal.
Il faut organiser le code différemment de manière à ne pas avoir besoin d'attendre...
OK, bon.
Normalement, les chemins de code qui passent par un block se terminent là , car ils sont exécutés sur un autre thread que le thread principal.
Du coup, c'est aussi normal à modifier le UI du code d'un block, en utilisant un appel dispatch_async qui se tournera sur le thread principal.
Je te demanderais, qu'est-ce qui devrait se passer après le retour de ta méthode qui passe le block au web service ?
Je me trouve d'accord avec zoc en disant que, peut-être, il faut reorganiser ton code pour qu'il prenne en compte les threads, en espérant que le code du web service n'exécute pas sur le thread principal.
Au contraire, tu peux, quand même, utiliser un predicate à la place du for..in
Donc puisque le fait de savoir si on a trouvé des éléments passe par retriveAllBookings et un WebService et donc par nature peut prendre du temps etc, ta méthode parent (qu'on va appeler "hasCheckedIn" par exemple) ne doit pas être une méthode qui retourne un BOOL (la valeur de "found" dans ton cas), mais une méthode qui ne retourne rien dans l'immédiat, et fournit la valeur de résultat au travers d'un bloc de complétion. Puisque pour savoir si tu as des réservations Checked-In, par nature cela se fait de manière asynchrone. Faut rester logique.
Faire une méthode synchrone qui va être obligée d'attendre que le block soit fini d'exécuter n'est pas une bonne idée car tu transformes du asynchrone (te permettant de continuer ton code sans bloquer ton thread principal pendant que la requête WebService est faite et la réponse analysée) en code synchrone donc bloquant, qui va bloquer le thread appelant en attendant d'avoir la réponse (ce qui peut être long si le réseau de l'utilisateur est pourri ou qu'il passe sous un tunnel !). Du coup si tu te mets à transformer du asynchrone en synchrone c'est sûrement qu'il y a un problème de conception. C'est possible dans l'absolu, mais c'est souvent révélateur d'une mauvaise idée.