rushelmet
rushelmet

Reputation: 305

Remove Observer iOS

I want to remove this observer in my code :

[self.noteLabel addObserver:self forKeyPath:@"contentSize" options:(NSKeyValueObservingOptionNew) context:NULL];

What is the good practice to remove it ? Thanks

EDIT

I want to remove this observer because I need to remove its parentView. Actually it crashes because of this observer. What would be the good practice to remove a subview with an observer ? Thanks for your help.

Upvotes: 0

Views: 746

Answers (3)

Christian Schnorr
Christian Schnorr

Reputation: 10776

Typically you start observing some key path in -init and stop doing so in -dealloc.

I would unregister yourself in -dealloc.

Upvotes: 0

Nat
Nat

Reputation: 12948

This is not completely safe what you've presented. You can use such code:

#pragma mark - KVO

static void *_myContextPointer = &_myContextPointer;
- (void)enableObserver:(BOOL)enable onObject:(id)object selector:(SEL)selector {
    NSString *selectorKeyPath = NSStringFromSelector(selector);
    if (enable) {
        [object addObserver:self forKeyPath:selectorKeyPath options:0 context:&_myContextPointer];
    } else {
        @try {
            [object removeObserver:self forKeyPath:selectorKeyPath context:&_myContextPointer];
        } @catch (NSException *__unused exception) {}
    }
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if (context != _myContextPointer) {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];

        return;
    }

    [self observerActionForKeyPath:keyPath ofObject:object change:change];
}

and ofc such code to handle your observer:

- (void)observerActionForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change {
    NSString *contentSizeKeyPath = NSStringFromSelector(@selector(contentSize));
    if ([keyPath isEqualToString:contentSizeKeyPath]) {
        // do something
    }
}

Then you just call it eg:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    [self enableObserver:YES onObject:self selector:@selector(contentSize)];
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];

    [self enableObserver:NO onObject:self selector:@selector(contentSize)];
}

Via using such code, your app won't crash because you remove observers few times in a row. Also you can't make a typo in your property name and it will dynamically change when you refactor your code. All KVO is in one place.

You can read more about safe KVO on NSHipster page.

Upvotes: 0

tbaranes
tbaranes

Reputation: 3590

Whenever you want to remove an observer, you just have to use removeObserverwith the right parameters.

[self.noteLabel removeObserver:self forKeyPath:@"contentSize"];

Upvotes: 1

Related Questions