【问题标题】:Multiple block operations called via addObserver:selector:name:object:通过 addObserver:selector:name:object 调用的多个块操作:
【发布时间】:2012-05-21 16:51:30
【问题描述】:

我有一个用户操作尝试连接到在线资源的应用。连接过程由第三方SDK 完成,成功或失败异步反馈。这由我配置为以任何一种方式发布通知的 appDelegate 处理。 (即 Dropbox 风格)。

下面,假设失败,UIAlertView 被调用的次数与执行操作的次数一样多。也就是如果我反复测试连接失败了,第一次block被调用一次,第二次block被调用两次,第3次被调用3次等等。就好像block操作没有被取消一样或从队列中删除。

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。

为什么会发生多次调用?有没有更好的使用块的方法?

【问题讨论】:

    标签: ios nsoperationqueue nsnotificationcenter


    【解决方案1】:

    您使用的方法的 Apple 文档说:

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

    换句话说,你不能在移除观察者时简单地传递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];
    
     });
    }];
    

    【讨论】:

    • 谢谢。试过但没有用。第二次在 id observer = ... 语句中收到 EXC_BAD_ACCESS。我简化了消除 opQ 并使用 [NSOperationQueue mainQueue] 的代码。同样的崩溃。消除了 GCD...同样的崩溃。
    • 好的,再挖掘一下,发现这个问题是 8477629 的副本。答案是添加 __block id observer = ...
    • 我打算在您发表评论之前建议使用__block id ......哈...我会更新答案...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-21
    相关资源
    最近更新 更多