Objective-C, annuler une file d'attente d'expédition à l'aide d'un événement d'interface utilisateur
Scénario:
- Utilisateur appuie sur un bouton demander un certain type de modification sur le carnet d'adresses.
- Une méthode est appelée au démarrage de cette modification et une alerte de vue s'affiche.
- Afin de montrer l'affichage des alertes et de garder l'INTERFACE utilisateur réactive, j'ai utilisé dispatch_queue:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ dispatch_sync(dispatch_get_main_queue(), ^{ //Show the alert view }); });
- Démarrer le processus de carnet d'adresses modification à l'aide de:
dispatch_async(modifyingAddressBookQueue, ^{});
Maintenant, je veux offrir à l'utilisateur la possibilité d'annuler le processus à tout moment (bien sûr avant de sauvegarder le carnet d'adresses). Alors, quand il appuie sur le bouton annuler dans l'alerte de la feuille, je veux accéder à l'envoi de bloc, jeu de certains BOOL pour arrêter le processus et de revenir le carnet d'adresses.
Le problème est, vous ne pouvez pas faire ça! vous ne pouvez pas accéder au bloc et le changement de la variable à l'intérieur d'elle car toutes les variables sont copiés qu'une seule fois. Tout changement de variables à l'intérieur du bloc, tout en étant exécuté ne pas être vus par le bloc.
Pour résumer: Comment arrêter une opération à l'aide d'une INTERFACE utilisateur événement?
Mise à jour:
Le code pour le processus:
- (void) startFixingModification {
_fixContacts = YES;
__block BOOL cancelled = NO;
dispatch_queue_t modifyingAddressBookQueue;
modifyingAddressBookQueue = dispatch_queue_create(sModifyingAddressBookQueueIdentifier,
NULL);
dispatch_async(modifyingAddressBookQueue, ^{
for (NSMutableDictionary *contactDictionary in _contactArray) {
if (!cancelled) {
break;
}
i = i + 1;
BOOL didFixContact = [self fixNumberInContactDictionary:contactDictionary];
if (!didFixContact) {
_fixedNumbers = _fixedNumbers - 1;
}
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_sync(dispatch_get_main_queue(), ^{
[self setAlertViewProgress:i];
});
});
}
});
cancelledPtr = &cancelled;
}
Code pour alertview (mon propre lib) délégué
- (void) alertViewProgressCancel:(ASAlertViewProgress *)alertView { //This is a private lib.
if (cancelledPtr)
{
NSLog(@"stopping");
*cancelledPtr = YES;
}
}
Dans l'interface, je déclare
BOOL* cancelledPtr;
Mise à jour 2:
C'est vraiment frustrant! pour le code suivant
for (NSMutableDictionary *contactDictionary in _contactArray) {
NSLog(@"%d", _cancelModification);
if (_cancelModification) {
break;
}
}
si _cancelModification est réglé sur OUI, la boucle est cassé et c'est OK. Une fois que j'en commentaire le NSLog ligne, le _cancelModification est négligé quand il se transforme en OUI!
source d'informationauteur Abdalrahman Shatou
Vous devez vous connecter pour publier un commentaire.
Si vous déclarez votre
BOOL
à l'aide de__block
alors il peut être changé à l'extérieur du bloc de l'exécution, et le bloc va voir la nouvelle valeur. Voir la documentation pour plus de détails.Un exemple:
Vous pouvez également utiliser un ivar dans votre classe pour stocker l'BOOL. Le bloc implicitement de faire une copie de
self
et accès à la ivar via que. Pas besoin de__block
.Approche 1
Créer un personnalisé dispatch_async méthode qui retourne un "annulable" bloquer.
Approche 2
La définition d'une macro pour l'exécution d'un bloc de manière asynchrone si une condition est validée:
Essayez d'appliquer l'exemple de code suivant à votre situation: