【问题标题】:iOS NSNotificationCenter Observer not being removediOS NSNotificationCenter 观察者没有被删除
【发布时间】:2014-06-20 18:43:03
【问题描述】:

我在 AppDelegate 中有以下代码。目的是创建几个观察者,然后调用一些代码。一旦该代码完成它就会发布一个通知,然后观察者应该删除两个观察者并调用完成处理程序。

我的问题是观察者似乎没有像我预期的那样被移除。通知已发布,NSLog 条目已写入控制台,因此我知道观察者正在工作。但是,在第二次调用时,NSLog 被调用了两次,第三次调用了 3 次等等。

我的想法是,这与从观察者运行的代码块中的删除有关,但是,我不确定如何解决这个问题(如果确实是这个问题的话)。

有人能解释一下我是如何做到这一点的吗?

谢谢。

-(void) application:(UIApplication *)application performFetchWithCompletionHandler:
(void (^)(UIBackgroundFetchResult))completionHandler {

    [[NSNotificationCenter defaultCenter] addObserverForName:@"fetchDidCompleteNewData" object:nil
                                                     queue:nil usingBlock:^(NSNotification *completed) {

                                                         //Remove Observers
                                                         [[NSNotificationCenter defaultCenter] removeObserver:self
                                                                                                         name:@"fetchDidCompleteNewData"
                                                                                                       object:nil];
                                                         [[NSNotificationCenter defaultCenter] removeObserver:self
                                                                                                         name:@"fetchDidCompleteNoData"
                                                                                                       object:nil];


                                                         // Post completion
                                                         completionHandler(UIBackgroundFetchResultNewData);
                                                         NSLog(@"Background fetch completed... New Data");
                                                     }];

    [[NSNotificationCenter defaultCenter] addObserverForName:@"fetchDidCompleteNoData" object:nil
                                                       queue:nil usingBlock:^(NSNotification *completed) {

                                                           //Remove Observers
                                                           [[NSNotificationCenter defaultCenter] removeObserver:self
                                                                                                           name:@"fetchDidCompleteNoData"
                                                                                                         object:nil];

                                                           [[NSNotificationCenter defaultCenter] removeObserver:self
                                                                                                           name:@"fetchDidCompleteNewData"
                                                                                                         object:nil];

                                                           //post completion
                                                           completionHandler(UIBackgroundFetchResultNoData);
                                                           NSLog(@"Background fetch completed... No New Data");

                                                       }];

    GetDetails *getDetails = [[GetDetails alloc] init];
    [getDetails backgroundRefresh];

}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];

    return YES;
}

【问题讨论】:

    标签: ios objective-c nsnotificationcenter observers


    【解决方案1】:

    您没有将self 注册为对象。此外,当块被addObserverForName: 压入堆栈时,该方法还没有返回,所以notificationnil

    使用block创建一个全局对象,例如

    __block __weak id notification;
    

    那么,

    notification =  [[NSNotificationCenter defaultCenter] addObserverForName:@"fetchDidCompleteNewData" object:nil queue:nil usingBlock:^(NSNotification *completed) {
    
       //Remove Observers
       [[NSNotificationCenter defaultCenter] removeObserver:notification];
    }];
    

    【讨论】:

    • 翻译:当使用addObserverForName 时,self 不是观察者,所以调用[center removeObserver:self ...] 不起作用。观察者是从addObserverForName 返回的对象,是观察者,您必须使用它,但是这很棘手,因为在定义块并将其传递给方法时它的值还不可用。使用__block 声明存储观察者结果的变量。
    【解决方案2】:

    我的想法是,这与移除在 从观察者运行的代码块,但是,我不确定 我该如何解决这个问题(如果这确实是问题所在)。

    有人能解释一下我是如何做到这一点的吗?

    当然。

    您可以通过不使用addObserverForName:object:queue:usingBlock: 方法而是使用addObserver:selector:name:object: 方法来轻松测试您的理论,其中selector 是您调用的函数的名称,而不是使用块。

    只需使用API guide for NSNotificationCenter 获取有关这些方法的详细信息,或者一般而言,由于您的问题是您可以使用哪些其他不需要块语句的方法,因此首先咨询 API 以检查替代工具在课堂上。

    【讨论】:

    • 感谢您的 cmets。非常感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多