UICollectionView calling scrollViewDidScroll: when popped from the navigation stack

Allen Zeng picture Allen Zeng · Mar 5, 2013 · Viewed 10.5k times · Source

I have a navigation controller, its root view controller is of type CollectionViewControllerA. Upon selecting an item, I have a fade out and expanding animation followed by a call to push a second view controller of type CollectionVewControllerB onto the stack:

CollectionViewControllerB *b = ... // construction of the view controller to be pushed
[UIView animateWithDuration:.3
                 animations:^{
                     self.collectionView.transform = CGAffineTransformMakeScale(1.5, 1.5);
                     self.collectionView.alpha = 0;
                 }
                 completion:^(BOOL s){
                     [self.navigationController pushViewController:b animated:NO];
                 }];

I pop the view controller in a similar way

[UIView animateWithDuration:.3
                 animations:^{
                     self.collectionView.transform = CGAffineTransformMakeScale(.3, .3);
                     self.collectionView.alpha = 0;
                 }
                 completion:^(BOOL s){
                     [self.navigationController popViewControllerAnimated:NO];
                 }];

The problem here is that the app crashes when popping the view controller. Reason:

*** -[CollectionViewControllerB scrollViewDidScroll:]: message sent to deallocated instance

I understand that the problem is because the popped view controller is destroyed, but why does scrollViewDidScroll: get called in the first place? Nothing changes the contentOffset of the collectionView in code, and there is no user interaction either. Unless changing the transform property also triggers the method to get called?

CollectionViewControllerB implements scrollViewDidScroll: because I need to disable vertical scrolling.

Meanwhile I have a very very messy hack to prevent the crash, that is before the animation, I add

self.collectionView.delegate = nil;

This stops the method from getting called. But there has to be a better way.

Can anyone shed some light on why scrollViewDidScroll: is called and how it can be stopped?

Answer

Allen Zeng picture Allen Zeng · Jul 25, 2013

It seems like the only way to solve the problem is what I have already done... setting the delegate to nil before the animation.

self.collectionView.delegate = nil;

Hopefully this helps someone else in the future.