When should I call removeObserver:forKeyPath from

2019-06-22 06:25发布

问题:

I have a ViewController class that has a property that is the model which I want to observe as properties on the model change. Within my model object I have a property that is periodically updated in the background of my application. As it updates, I need to execute code within my ViewController.

To do this, I create an observer on my model from within my ViewController viewDidLoad method.

[ModelObject addObserver:self 
              forKeyPath:@"State" 
                 options:NSKeyValueObservingOptionNew 
                 context:nil];

As you can see, this is nothing special and the observation method behaves as it should so long as I leave the view displayed on my screen. If I remove the above view from the parent view, I get an EXC_BAD_ACCESS error message when my ModelObject instance Mode property changes. Specifically, my app crashes at the line that is updating the Mode property and I receive the mostly useless EXC_BAD_ACCESS on the following line of code within the ModelObject instance.

//This is located in a method that periodically toggles the value of "State"
[self setState: 2];

I would assume the solution to this problem is to call [ModelObject removeObserver: self forKeyPath:@"State"] from somewhere within my ViewController when it is removed from it's parent subview array. However, I have added that line of code within my viewDidUnload method but I've found the the viewDidUnload method isn't being called. I'm not sure if that is the right place, but it needs to go some where.

What might I be doing incorrectly? I know the problem is KVO related because if I remove the observation, the application works without any problem. My model instance can toggle this value as much as it wants and my application never crashes. What should I do to be sure that my observer is removed correctly when the observing view is being removed from it's parent's subview array?

回答1:

I generally like to put the addObserver: and removeObserver: in viewWillAppear: and viewWillDisappear:. I find these are more reliable bookends than viewDidLoad and viewDidUnload.



回答2:

You should remove it in the view controller's -dealloc