gpt4 book ai didi

ios - UICollectionView 使用自定义布局抛出未捕获的异常

转载 作者:行者123 更新时间:2023-11-29 12:15:34 25 4
gpt4 key购买 nike

我正在使用具有自定义布局的 Collection View ,调用我第一次从 API 收到的 web 服务返回 20 个对象,第二次将返回 1 个对象,同时重新加载数据应用程序抛出以下错误。

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: UICollectionView received layout attributes for a cell with an index path that does not exist: {length = 2, path = 0 - 0}

创建新布局的代码片段

-(void)doNewLayout 
{
id<UICollectionViewDelegateJSPintLayout> delegate = (id<UICollectionViewDelegateJSPintLayout>)self.collectionView.delegate;

// get column width from delegate. If the method isn't implemented fall back to our property
NSUInteger columnWidth = self.columnWidth;
if(delegate && [delegate respondsToSelector:@selector(columnWidthForCollectionView:layout:)])
{
columnWidth = [delegate columnWidthForCollectionView:self.collectionView
layout:self];
}

// find out how many cells there are
NSUInteger cellCount = [self.collectionView numberOfItemsInSection:0];

// get max number of columns from the delegate. If the method isn't implemented, fall back to our property
NSUInteger maximumNumberOfColumns = self.numberOfColumns;
if(delegate && [delegate respondsToSelector:@selector(maximumNumberOfColumnsForCollectionView:layout:)]){
maximumNumberOfColumns = [delegate maximumNumberOfColumnsForCollectionView:self.collectionView layout:self];
}

// build an array of all the cell heights.
NSMutableArray* cellHeights = [NSMutableArray arrayWithCapacity:cellCount];
for(NSUInteger cellIndex = 0; cellIndex < cellCount; ++cellIndex)
{
CGFloat itemHeight = self.itemHeight; // set default item size, then optionally override it
if(delegate && [delegate respondsToSelector:@selector(collectionView:layout:heightForItemAtIndexPath:)])
{
itemHeight = [delegate collectionView:self.collectionView
layout:self
heightForItemAtIndexPath:[NSIndexPath indexPathForItem:cellIndex
inSection:0]];
}

cellHeights[cellIndex] = @(itemHeight);
}

// now build the array of layout attributes
self.pendingLayoutAttributes = [NSMutableArray arrayWithCapacity:cellCount];

// will need an array of column heights
CGFloat* columnHeights = calloc(maximumNumberOfColumns,sizeof(CGFloat)); // calloc() initializes to zero.
CGFloat contentHeight = 0.0;
CGFloat contentWidth = 0.0;
for(NSUInteger cellIndex = 0; cellIndex < cellCount; ++cellIndex)
{
CGFloat itemHeight = [cellHeights[cellIndex] floatValue];

// find shortest column
NSUInteger useColumn = 0;
CGFloat shortestHeight = DBL_MAX;
for(NSUInteger col = 0; col < maximumNumberOfColumns; ++col)
{
if(columnHeights[col] < shortestHeight)
{
useColumn = col;
shortestHeight = columnHeights[col];
}
}

NSIndexPath* indexPath = [NSIndexPath indexPathForItem:cellIndex
inSection:0];
UICollectionViewLayoutAttributes* layoutAttributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];

layoutAttributes.size = CGSizeMake(columnWidth,itemHeight);
layoutAttributes.center = CGPointMake((useColumn * (columnWidth + self.interitemSpacing)) + (columnWidth / 2.0),columnHeights[useColumn] + (itemHeight / 2.0));
self.pendingLayoutAttributes[cellIndex] = layoutAttributes;
columnHeights[useColumn] += itemHeight;
if(columnHeights[useColumn] > contentHeight)
contentHeight = columnHeights[useColumn];
CGFloat rightEdge = (useColumn * (columnWidth + self.interitemSpacing)) + columnWidth;
if(rightEdge > contentWidth)
contentWidth = rightEdge;
columnHeights[useColumn] += self.lineSpacing;
}
self.contentSize = CGSizeMake(contentWidth,contentHeight+100);

free(columnHeights);
}

任何快速解决方案将不胜感激。谢谢

最佳答案

有几件事需要考虑,因为您是自定义布局,所以您需要为每个 indexPath 创建 layoutAttribute。在你的情况下,你的数据源数组计数和 offerModel.arrayOffersself.pendingLayoutAttributes 应该是相同的,如果不是那么它可能是问题,如果 offerModel .arrayOffersself.pendingLayoutAttributes 有更多的项目。

如果您正在异步加载数据,那么请确保当您在 arraysOffers 中添加行时也在 customLayout pendLayoutAttributes 中添加 layoutAttributes,我认为您目前没有这样做,通过添加一个方法来实现并为创建 layoutAttributes 的对象提供新的 indexPaths

我经常这样

- (void)insertItems:(NSArray*)items
{
NSInteger startIndex = <start index for new item>;
[self.items addObjectsFromArray:items];
[self calculateLayoutForItems:items startIndex:startIndex];
}

这个方法会计算layoutAttributes

- (void)calculateLayoutForItems:(NSArray*)items startIndex:(NSInteger)startIndex
{
// collection view and loop over them as well and nest indexPath creation

NSInteger section = 0;
NSInteger endIndex = self.items.count;

// Lets create indexPaths for provided items and get there frames
for (NSInteger index = startIndex ;index < endIndex; index++)
{
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:index inSection:section];
CGRect frame = [self frameForItemAtIndexPath:indexPath];// call your method for frame at indexPath

UICollectionViewLayoutAttributes *itemAttributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
itemAttributes.frame = frame;
self.pendingLayoutAttributes[indexPath] = itemAttributes; // you can use your index
}
}

现在,当您在数据源中获得更多项目时,在 customLayoutObject 上调用此方法 [self.customLayout insertItems:newItemsArray];

此外,如果您已经存储了属性,那么值得在自定义布局中覆盖无效方法以将所有属性重置为初始状态,然后你可以在reloadData方法之前invalidatecustomLayout,然后collection view会强制它重新计算布局。

关于ios - UICollectionView 使用自定义布局抛出未捕获的异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32119010/

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