UICollectionView 调用 scrollViewDidScroll:从导航堆栈中弹出时

Posted

技术标签:

【中文标题】UICollectionView 调用 scrollViewDidScroll:从导航堆栈中弹出时【英文标题】:UICollectionView calling scrollViewDidScroll: when popped from the navigation stack 【发布时间】:2013-02-19 09:47:37 【问题描述】:

我有一个导航控制器,它的根视图控制器的类型是CollectionViewControllerA。选择一个项目后,我有一个淡出和扩展动画,然后调用将CollectionVewControllerB 类型的第二个视图控制器推入堆栈:

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];
                 ];

我以类似的方式弹出视图控制器

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

这里的问题是应用程序在弹出视图控制器时崩溃。原因:

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

我知道问题是因为弹出的视图控制器被破坏了,但是为什么首先调用scrollViewDidScroll:?代码中collectionViewcontentOffset 没有任何变化,也没有用户交互。除非更改transform 属性也会触发方法被调用?

CollectionViewControllerB 实现 scrollViewDidScroll: 因为我需要禁用垂直滚动。

同时我有一个非常非常混乱的 hack 来防止崩溃,也就是在动画之前,我添加了

self.collectionView.delegate = nil;

这会阻止该方法被调用。但必须有更好的方法。

谁能解释为什么调用scrollViewDidScroll: 以及如何停止它?

【问题讨论】:

我刚刚遇到了同样的问题,但使用了 segues。我的解决方案和你的一样;在 viewWillDisappear 上,代表为零。不知道为什么会这样。一定是popping改变了contentOffset,但我不确定如何或为什么。 我想取消委托是一个很好的解决方案......看到对象无论如何都会被销毁。 【参考方案1】:

似乎解决问题的唯一方法就是我已经完成的操作...在动画之前将代理设置为 nil。

self.collectionView.delegate = nil;

希望这对将来的其他人有所帮助。

【讨论】:

我在 -(void)dealloc 方法中添加了它。 @md_develop 这是放置它的最佳位置 我刚刚用 UITableView 发生了这种情况。我不知道为什么,但是将委托设置为 nil 修复了它。但是,出于某种原因,这感觉就像是 hack。 @Johnny 我会说这是一个 hack。我看不出这种行为的原因,直到 Apple 修复它(我认为这永远不会发生),这似乎是最好的选择。 @SodbilegGansukh 所有证据都表明这是一个错误,因为我从来没有将代表设置为 nil 来处理其他任何事情。我不知道它是否已修复,从持续的兴趣来看,它可能不是......【参考方案2】:

在您的视图控制器中设置self.automaticallyAdjustsScrollViewInsets = NO;

我遇到了类似的问题,发现在离开页面时,contentOffset 每次都会更改 20。

我发现在我的视图控制器中设置这个属性停止了这种变化,因此不再调用scrollViewDidScroll。结果是视图控制器会自动调整内容插入以适应状态栏、导航栏等的变化。即使您离开。

我认为这是一个更好的解决方案,并且可以正确解释为什么调用滚动方法。

【讨论】:

对我来说,self.automaticallyAdjustsScrollViewInsets = NO; 导致了崩溃。将其设置回YES,即可解决问题。这很奇怪。【参考方案3】:

你可以在你的控制器中试试这个。

[self setEdgesForExtendedLayout:UIRectEdgeNone];

希望这会对你有所帮助。

【讨论】:

以上是关于UICollectionView 调用 scrollViewDidScroll:从导航堆栈中弹出时的主要内容,如果未能解决你的问题,请参考以下文章

调用 didHighlightItemAtIndexPath 而不调用 UICollectionView 的 didSelectItemAtIndexPath

未调用 UIcollectionView 的 didDeselectItemAt 但调用了 didSelectItemAt?

在 sizeForItemAtIndexPath 中调用 UICollectionView 单元

重新加载和调用requestImageForAsset时UICollectionView闪烁

未调用 UICollectionView 的 didSelectItemAtIndexPath

未调用 TableViewCell 内的 UICollectionView