需要两次调用removeObserver

时间:2014-07-16 08:31:14

标签: ios objective-c key-value-observing dealloc

我有一个观点,就是在init上观察自己的值:

[self addObserver:self forKeyPath:@"focusPointOfInterestIndicator" options:0 context:kSRCameraViewObserverContext];
[self addObserver:self forKeyPath:@"exposurePointOfInterestIndicator" options:0 context:kSRCameraViewObserverContext];
[self addObserver:self forKeyPath:@"paused" options:0 context:kSRCameraViewObserverContext];
[self addObserver:self forKeyPath:@"previewLayerGravity" options:0 context:kSRCameraViewObserverContext];

dealloc上,观察者被移除,因为他们应该是这样的:

[self removeObserver:self forKeyPath:@"focusPointOfInterestIndicator"];
[self removeObserver:self forKeyPath:@"exposurePointOfInterestIndicator"];
[self removeObserver:self forKeyPath:@"paused"];
[self removeObserver:self forKeyPath:@"previewLayerGravity"];

但是除非调用它两次(有或没有上下文,不会改变任何东西),当视图被释放时我崩溃导致仍然观察到该值。 但是我很确定观察者只被添加一次(因为它是在init的对象中)。

我只是想知道为什么它可以被注册两次?或者通过调用它两次,它让对象有效地删除观察者?如果有人有任何线索?

3 个答案:

答案 0 :(得分:2)

initNSObjet主要初始值设定项,这意味着必须在Apple的initWithCoder / initWithFrame实施中调用init像[super init];

这样的东西

所以你的sharedSetup被调用了两次

编辑(感谢And Ainu):

更具体地说,init调用UIView方法的initWithFrame方法。

答案 1 :(得分:1)

如果每次移除观察者时都使用try catch,那么这是一种很好的做法。

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    @try {
        [[NSNotificationCenter defaultCenter] removeObserver:self name:@"LocationSelected" object:nil];
    } @catch (id anException){
        //do nothing, obviously it wasn't attached because an exception was thrown
   }   
    [[NSNotificationCenter defaultCenter] addObserverForName:@"LocationSelected" object:nil queue:[NSOperationQueue mainQueue] usingBlock: ^(NSNotification *not) {
       //Someone posted the notification handle it here
    }];
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
     @try {
         [[NSNotificationCenter defaultCenter] removeObserver:self name:@"LocationSelected" object:nil];
     } @catch (id anException){
         //do nothing, obviously it wasn't attached because an exception was thrown
     }
}

答案 2 :(得分:0)

您可以做的另一件事是,不是在init方法中观察,而是在loadViewawakeFromNib方法中替换相同的方法。然后它不会再调用两次。