UPDATE: see my comment for a better way to fix this. However, to understand what is happening, this question is still informative ... (final update)
Solved (at least in my case). Here's what happens:
My view controller is used to display search results and saves these search results as an array of model objects. I use a custom subclass of UITableViewCell to display each search result and, as part of its configuration, store the associated model object (search result) inside the property of the custom cell, name it myCell.modelObject .
As I already noted, an error occurred at every search, except the original one. For debugging, I set a symbolic breakpoint on NSKVODeallocateBreak and saw that this happens when reusing one of my user cells:
- (void)configureWithModelObject:(ModelObject*)aModelObject { // @property (nonatomic, retain) ModelObject *modelObject; self.modelObject = aModelObject; // <-- NSKVODeallocateBreak paused here .... }
So, my view controller, having received the second set of search results, will free an array containing the source objects of the search model. Those that are still stored by my reusable instances of user cells will adhere, at least until these cells are reused again. At this point, when self.modelObject is updated, the previous modelObject is again freed and finally freed , but since the cell that observed it was not freed but was reused instead, my [modelObject removeObserver ...] call in [myCell dealloc] has not been called.
Solution: When setting up my custom cell, I need to check if the model object is installed, which is a sign of reuse of this cell. If so, I stop observing the original modelObject before updating the property:
- (void)configureWithModelObject:(ModelObject*)aModelObject { if(modelObject != nil) {
Note I still need to call [modelObject removeObserver ...] in [cell dealloc] to handle the situation when the view manager itself is freed.
I hope this is useful to others with a similar pattern.
Best Steve