Search code examples
iosobjective-cxcodeuitableviewkey-value-observing

Main Thread Crash Using Key Value Observing And ECSlidingView Library


I am using NSKeyValueChange to refresh images appeared in the tableview after getting them from the web service.

- (void)observeValueForKeyPath:(NSString *)keyPath
              ofObject:(id)object
                change:(NSDictionary *)change
               context:(void *)context {

if ([keyPath isEqual:@"thumbnail"]) {
  UIImage* newImage = [change objectForKey:NSKeyValueChangeNewKey];
  if (newImage != (id)[NSNull null]) {
    self.thumbContainer.image = newImage;
    [self.thumbContainer setNeedsLayout];
  }
}

}

and

[item addObserver:cell forKeyPath:@"thumbnail" options:NSKeyValueObservingOptionNew context:NULL];

It was all working fine until i added the whole navigation inside a third party library named ECSlidingViewController to have a left side navigation similar to Facebook and Sparrow Mail app.

Now my app is getting crashed and following is the image i get when i try to load more cells in the tableview when it gets to the bottom.

enter image description here

As you can see in the image above, it is not enough for me to troubleshoot where exactly the problem is. I have tried checking similar problems on StackOverflow related to Main Thread crashes but they didn't help me.

Can somebody please look into it and where could the problem is. Thanks in advance.

UPDATE: I am able to run the program but when i scroll down to reveal more cells, this issue cause the program to crash.


Solution

  • It has crashed at msgSend call, that means it send a function call on a bad pointer (not an obj-c object).

    [item addObserver:cell forKeyPath:@"thumbnail" options:NSKeyValueObservingOptionNew context:NULL];
    

    You made an implicit subscription. When item is freed, the observer is still registering theitem.

    From Apple doc: addObserver:forKeyPath:options:context: ... Neither the receiver, nor anObserver, are retained

    So in order to keep it clean you must implement removeObserver:forKeyPath:context: before item will be freed. I'm guessing you are KVO it with your cells, wich is a bad idea since you don't have access to the memory management of them (you are responsive for the allocation, the tableViewcell manage itself how much cells it needs).

    So subscribe and unsubscribe KVO where you can.

    I hope you get the idea ;)