Allen Zeng
Allen Zeng

Reputation: 2665

UICollectionView calling scrollViewDidScroll: when popped from the navigation stack

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?

Upvotes: 28

Views: 11455

Answers (3)

wxhui
wxhui

Reputation: 1

You can try this in your controller .

[self setEdgesForExtendedLayout:UIRectEdgeNone];

Hope this would help you.

Upvotes: 0

jack moseley
jack moseley

Reputation: 429

Set self.automaticallyAdjustsScrollViewInsets = NO; inside your view controller.

I had a problem similar to this, and found that on navigating away from the page, the contentOffset was changing by 20 every time.

I found that setting this property inside my view controller stopped this changing, and therefor scrollViewDidScroll was no longer being called. Turns out the view controller automatically adjusts content insets for changes in status bar, nav bar etc.. even when you navigate away.

I think this is a better solution and proper explanation as to why the scrolling method was being called.

Upvotes: 9

Allen Zeng
Allen Zeng

Reputation: 2665

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.

Upvotes: 56

Related Questions