gpt4 book ai didi

ios - UICollectionViewFlowLayout 子类在滚动和重新加载时崩溃访问超出范围的数组

转载 作者:可可西里 更新时间:2023-11-01 03:28:45 27 4
gpt4 key购买 nike

我有一个 UICollectionView,它使用 UICollectionViewFlowLayout 的自定义子类,使节标题在滚动时粘在屏幕顶部,就像 UITableView 的普通样式一样。我的代码基于这种方法:

http://blog.radi.ws/post/32905838158/sticky-headers-for-uicollectionview-using

此外, Collection View 设置为在用户滚动到底部时加载更多结果。也就是说,当用户到达 Collection View 的底部时,网络请求会加载更多数据,然后重新加载 Collection View ,即调用 reloadData。

它似乎运行良好,除了我通过运行 iOS 7 和 7.1 的 TestFlight 从 beta 测试人员那里收到了一些崩溃报告,他们说当他们向下滚动到底部时偶尔会发生以下情况(即触发更多结果加载)很快:

*** -[__NSArrayM objectAtIndex:]: index 28 beyond bounds [0 .. 16]
PRIMARY THREAD THREAD 0

__exceptionPreprocess
objc_exception_throw
-[__NSArrayM objectAtIndex:]
-[UICollectionViewFlowLayout(Internal) _frameForItemAtSection:andRow:usingData:]
-[UICollectionViewFlowLayout layoutAttributesForItemAtIndexPath:usingData:]
-[UICollectionViewFlowLayout layoutAttributesForItemAtIndexPath:]
-[MyCustomCollectionViewFlowLayout layoutAttributesForItemAtIndexPath:]
-[MyCustomCollectionViewFlowLayout layoutAttributesForSupplementaryViewOfKind:atIndexPath:]
-[MyCustomCollectionViewFlowLayout layoutAttributesForElementsInRect:]
-[UICollectionViewData validateLayoutInRect:]_block_invoke
-[UICollectionViewData validateLayoutInRect:]
-[UICollectionView layoutSubviews]
-[UIView(CALayerDelegate) layoutSublayersOfLayer:]
-[CALayer layoutSublayers]

似乎当我的自定义流布局代码调用 [self.collectionView numberOfItemsInSection:someSection] 来获取部分最后一项的布局属性时,该调用会根据新加载的数据返回(例如,在这种情况下,一个部分现在有 29 个项目)但默认流布局的内部仍在使用某种缓存数据(例如,在这种情况下,该部分只有 17 个项目)。不幸的是,我自己无法重现崩溃,即使是经历过崩溃的 Beta 测试人员也无法始终如一地重现。

知道那里发生了什么吗?

最佳答案

编辑 2,根据 2nd BenRB 的评论。

当 dataSource 更新并且您调用 reloadData 时,后者实际上会使 Collection View 中的所有内容无效。然而,启动刷新过程的逻辑和确切顺序发生在默认流布局中,对我们是隐藏的。

特别地,默认流布局有它自己的私有(private)_prepareLayout(确切地说,带下划线)方法,它独立于prepareLayout 及其子类提供的重载.

顺便说一下,

prepareLayout(没有下划线)基本流布局类的默认实现什么都不做。

在刷新过程中,默认流布局使其子类有机会通过 layoutAttributesForElementsInRect:layoutAttributesForItemAtIndexPath:“回调”提供更多信息(例如,额外的 layoutAttributes)。为了保证基类的数据和各自的 indexPath/layoutAttributes 数组之间的一致性,对相应“super”的调用应该只发生在这些各自的方法中:

  • [super layoutAttributesForElementsInRect:] 仅在重载 [layoutAttributesForElementsInRect:]

  • [super layoutAttributesForItemAtIndexPath:] 仅在重载的 [layoutAttributesForItemAtIndexPath:] 中,

这些方法之间不应发生交叉调用,至少索引路径不是由它们相应的“ super ”方法提供的,因为我们不确切知道内部发生了什么

我与我的 Collection View 斗争了很长时间,最终以唯一的工作序列结束:

  1. 通过直接访问数据源(无需 Collection View 的 numberOfItemsInSection: 的中介)来准备附加布局数据,并将该数据存储在子类的对象中,例如在字典属性中,使用 indexPath 作为键。我在重载的 [prepareLayout] 中执行此操作。

  2. 当基类通过回调请求此信息时,将存储的布局数据提供给基类​​:

//layoutAttributesForElementsInRect

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {

//calls super to get the array of layoutAttributes initialised by the base class
**NSArray *array = [super layoutAttributesForElementsInRect:rect];**

for(MyLayoutAttributes *la in array)

if(la.representedElementCategory == UICollectionElementCategoryCell ){
NSIndexPath indexPath = la.indexPath //only this indexPath can be used during the call to layoutAttributesForItemAtIndexPath:!!!
//extracts custom layout data from a layouts dictionary
MyLayoutAttributes *cellLayout = layouts[la.indexPath];
//sets additional properties
la.this = cellLayout.this
la.that = cellLayout.that
...
}
....
return array;
}

//layoutAttributesForItemAtIndexPath:

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {

MyLayoutAttributes *la = (MyLayoutAttributes *)[super layoutAttributesForItemAtIndexPath:indexPath ];

if(la.representedElementCategory == UICollectionElementCategoryCell ){
NSIndexPath indexPath = la.indexPath //only this indexPath can be used during the call !!!
//extracts custom layout data from a layouts dictionary using indexPath as a key
MyLayoutAttributes *cellLayout = layouts[la.indexPath];
//sets additional properties
la.this = cellLayout.this
la.that = cellLayout.that
}
return la;
}

关于ios - UICollectionViewFlowLayout 子类在滚动和重新加载时崩溃访问超出范围的数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24616797/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com