我有一个应用,其中用户操作尝试连接到在线资源。连接过程由thirdPartySDK完成,并且异步地发回成功或失败信号。这是由我配置为以任一方式发布通知的appDelegate处理的。 (即Dropbox风格)。
下面,假设失败, UIAlertView 会在执行操作时被多次调用。也就是说,如果我反复测试连接并且它失败了,第一次调用块一次,第二次调用块两次,第三次调用3次,等等。如果块操作没有被取消或从队列中删除。
if (!opQ) {
opQ = [[NSOperationQueue alloc] init];
}
[[NSNotificationCenter defaultCenter] addObserverForName:LINK_NOTIFICATION_FAILURE object:nil queue:opQ usingBlock:^(NSNotification *aNotification) {
dispatch_async(dispatch_get_main_queue(),
^{
[[[UIAlertView alloc] initWithTitle:@"Network_Account_Not_Linked" message:@"Your_attempt_to_link_your_account_ended_unsuccessfully"
delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show];
[[NSNotificationCenter defaultCenter] removeObserver:self];
});
}];
问题似乎与 addObserverForName:object:queue:usingBlock: 有关。我使用 addObserver:selector:name:object: 进行了测试,其工作正常(每个通知执行一次选择器)。使用块更方便,使代码更具可读性并允许访问局部变量,因此我的动机。
我在NSBlockOperation线程中尝试了 [opQ cancelAllOperations] ,而dispatch_async( opQ 就在那时根据调试器“超出范围”。此外,使用 [NSOperationQueue mainQueue] ,但结果类似。此外,我还尝试在注册通知之前先使用新的opQ ... nada。
为什么会发生多个通话?有没有更好的方法使用块?
答案 0 :(得分:3)
您正在使用的方法的Apple文档说:
要取消注册观察,请将此方法返回的对象传递给removeObserver:。您必须在addObserverForName指定的任何对象之前调用removeObserver:或removeObserver:name:object:object:queue:usingBlock:is deallocated。
换句话说,你不能只是在移除观察者时简单地传递self
。
尝试:
__block id observer = [[NSNotificationCenter defaultCenter] addObserverForName:LINK_NOTIFICATION_FAILURE object:nil queue:opQ usingBlock:^(NSNotification *aNotification) {
dispatch_async(dispatch_get_main_queue(),
^{
[[[UIAlertView alloc] initWithTitle:@"Network_Account_Not_Linked" message:@"Your_attempt_to_link_your_account_ended_unsuccessfully"
delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show];
[[NSNotificationCenter defaultCenter] removeObserver:observer];
});
}];