Je suis encore nouveau sur les blocs dans l'objective-c et je me request si j'ai ce code correct. Je ne suis pas sûr s'il suffit de supprimer l'observateur ou si je dois appeler removeObserver: name: object:
-(void) scan { Scanner *scanner = [[Scanner alloc] init]; id scanComplete = [[NSNotificationCenter defaultCenter] addObserverForName:@"ScanComplete" object:scanner queue:nil usingBlock:^(NSNotification *notification){ /* do something */ [[NSNotificationCenter defaultCenter] removeObserver:scanComplete]; [scanner release]; }]; [scanner startScan]; }
Mise à jour: Je reçois EXC_BAD_ACCESS
intermittent de ce bloc, donc cela ne peut pas être correct.
Déclarez la variable scanComplete
avant de définir le bloc lui-même.
La raison pour laquelle vous devez faire cela est parce que vous essayez d'accéder à une variable qui n'existe pas dans le bloc au moment de la définition puisque la variable elle-même n'a pas encore été assignée.
Qu'est-ce que EXC_BAD_ACCESS
? Eh bien, c'est une exception qui est levée lorsque vous essayez d'accéder à une reference qui n'existe pas. C'est exactement le cas dans votre exemple.
Donc, si vous déclarez la variable avant le bloc lui-même, alors cela devrait fonctionner:
-(void) scan { Scanner *scanner = [[Scanner alloc] init]; __block id scanComplete; scanComplete = [[NSNotificationCenter defaultCenter] addObserverForName:@"ScanComplete" object:scanner queue:nil usingBlock:^(NSNotification *notification){ /* do something */ [[NSNotificationCenter defaultCenter] removeObserver:scanComplete]; [scanner release]; }]; [scanner startScan]; }
Vous ne devriez pas vous désinscrire dans le bloc de registre. Au lieu de cela, stockez le jeton renvoyé par addObserverForName
(dans ce cas, votre scanComplete
) en tant que variable d'instance ou dans une collection qui est une variable d'instance et désinscrivez-vous plus tard lorsque vous êtes sur le sharepoint disparaître. Ce que je fais est de garder un NSMutableSet appelé observers
. Alors:
id ob = [[NSNotificationCenter defaultCenter] addObserverForName:@"whatever" object:nil queue:nil usingBlock:^(NSNotification *note) { // ... whatever ... }]; [self->observers addObject:ob];
Et plus tard:
for (id ob in self->observers) [[NSNotificationCenter defaultCenter] removeObserver:ob]; self->observers = nil;
Apple Document sur cette méthode:
L'exemple suivant montre comment vous pouvez vous inscrire pour recevoir des notifications de modification des parameters régionaux.
NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; NSOperationQueue *mainQueue = [NSOperationQueue mainQueue]; self.localeChangeObserver = [center addObserverForName:NSCurrentLocaleDidChangeNotification object:nil queue:mainQueue usingBlock:^(NSNotification *note) { NSLog(@"The user's locale changed to: %@", [[NSLocale currentLocale] localeIdentifier]); }];
Pour annuler l'logging des observations, vous passez l'object renvoyé par cette méthode à removeObserver :. Vous devez appeler removeObserver: ou removeObserver: name: object: avant tout object spécifié par addObserverForName: object: queue: usingBlock: est désalloué.
NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; [center removeObserver:self.localeChangeObserver];
La scope du bloc n'a pas l'autorisation de libérer l'object scanner. Si vous n'utilisez pas le garbage collection, la suppression de la release
et la release
automatique du scanner ( [[[Scanner alloc] init] autorelease]
) devraient faire l'affaire.
Vous devriez également pouvoir déplacer l'appel vers removeObserver
en toute removeObserver
dehors du bloc.
Dans le cas de EXC_BAD_ACCESS
: Entrer bt
dans la window de la console après le plantage de l'application vous donnera un backtrace, et devrait vous informer où l'erreur s'est produite.