正确pipe理addObserverForName:object:queue:usingBlock:

我仍然是新来的块在objective-c,并想知道如果我有这个伪代码正确。 我不确定是否足以删除观察者,或者我必须调用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]; } 

更新:我从这个块中收到间歇性的EXC_BAD_ACCESS ,所以这是不对的。

在定义块本身之前声明scanCompletevariables。

你需要这样做的原因是因为你正试图访问一个在定义时不存在的variables,因为variables本身还没有被分配。

什么是EXC_BAD_ACCESS ? 那么,当你试图访问一个不存在的引用时,这是一个exception。 所以在你的例子中就是这样。

所以如果你在块本身之前声明variables,那么它应该工作:

 -(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]; } 

你不应该在寄存器块中取消注册。 相反,将从addObserverForName (在本例中为scanComplete )返回的标记存储为实例variables,或者存储在作为实例variables的集合中,稍后在您即将离开时(例如dealloc )取消注册。 我所做的就是保留一个名为observers的NSMutableSet。 所以:

 id ob = [[NSNotificationCenter defaultCenter] addObserverForName:@"whatever" object:nil queue:nil usingBlock:^(NSNotification *note) { // ... whatever ... }]; [self->observers addObject:ob]; 

再后来:

 for (id ob in self->observers) [[NSNotificationCenter defaultCenter] removeObserver:ob]; self->observers = nil; 

关于这个方法的Apple文档:

以下示例显示如何注册以接收区域设置更改通知。

 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]); }]; 

要取消注册观察,请将此方法返回的对象传递给removeObserver :. 您必须在释放由addObserverForName:object:queue:usingBlock:指定的任何对象之前调用removeObserver:或removeObserver:name:object:。

 NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; [center removeObserver:self.localeChangeObserver]; 

该块的范围没有权限释放扫描仪对象。 如果你不使用垃圾收集,删除release ,并使扫描仪autorelease( [[[Scanner alloc] init] autorelease] )应该做的伎俩。

您还应该能够安全地将呼叫移到removeObserver外部的removeObserver

对于EXC_BAD_ACCESS的情况:在应用程序崩溃之后,在控制台窗口中inputbt会给你一个回溯,并且会通知你错误发生的地方。