陈旧数据的UICollectionView断言错误

时间:2013-08-20 15:26:28

标签: uicollectionview ios7

在尝试从我的集合视图中卸载一批图像然后用另一批替换它们的过程中,我遇到了一个错误,这取决于原始图像组或后续图像组是否多于或少于预期替换,发生断言错误,说:

*** Assertion failure in -[UICollectionViewData validateLayoutInRect:], 
/SourceCache/UIKit_Sim/UIKit-2891.1/UICollectionViewData.m:341
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', 
reason: 'UICollectionView recieved layout attributes for a cell with an 
index path that does not exist: <NSIndexPath: 0xb141c60> {length = 2, path = 0 - 2}

在这种情况下,现有的图像计数列表为5,新的图像列表计数为2.因此,当它到达第三个图像时 - 发生异常 - 表明UI CollectionViewDataDelegate不知道其中的更改数据流。

有关如何确保UICollectionView引用新图像的任何建议?当然我叫'reloadData'......

谢谢

21 个答案:

答案 0 :(得分:85)

我遇到了同样的问题。代码在6.1下运行,在7.0下崩溃 我通过以下方式解决了这个问题:

在功能

-(NSInteger) numberOfSectionsInCollectionView:(UICollectionView *)collectionView

我打电话

[myCollectionView.collectionViewLayout invalidateLayout];

就是这样。

答案 1 :(得分:22)

使用iOS 10和11,这有助于:

collectionView.reloadData()
collectionView.collectionViewLayout.invalidateLayout()

无效布局应该在重新加载数据之后。

答案 2 :(得分:21)

Dominic Sanderuser1544494都是正确的,他们的解决方案很好。

不幸的是,我注意到如果你设置minimumLineSpacingForSectionAtIndexminimumInteritemSpacingForSectionAtIndex,你的collectionView的外观将会中断(迟早)。

invalidateLayout放入viewWillLayoutSubviews回答此问题并帮助保留viewCollection的外观。

- (void)viewWillLayoutSubviews
{
    [super viewWillLayoutSubviews];
    [viewCollection.collectionViewLayout invalidateLayout];
}

答案 3 :(得分:12)

这很简单。 就像下面的句子一样。

'UICollectionView recieved layout attributes for a cell with an 
index path that does not exist: <NSIndexPath: 0xb141c60> {length = 2, path = 0 - 2}

这意味着dataSouce上没有indexPath(0,2)。 但是,您的UICollectionViewLayout为indexPath(0,2)返回UICollectionViewLayoutAttributes。

您应该返回仅存在于dataSouce上的UICollectionViewLayoutAttributes。


我认为它已经从iOS7改变了。

答案 4 :(得分:10)

我的问题是我在UICollectionViews内有两个UIViewController。我将UICollectionViews连接到同一个UICollectionViewLayout子类。我通过将每个UICollectionView更改为拥有自己的UICollectionViewLayout子类来解决此问题。

来源:This Question

答案 5 :(得分:4)

我通过更新我的集合视图数据源修复了此崩溃:

- (NSInteger)collectionView:(UICollectionView *)collectionView
     numberOfItemsInSection:(NSInteger)section
{
    [collectionView.collectionViewLayout invalidateLayout];
    return collectionArray.count;
}

答案 6 :(得分:2)

修改了Collection View的内容后,我遇到了这个问题。在我的情况下工作的解决方案是重新加载后使布局无效。在重新加载之前执行此操作将无效。

[collectionView reloadData];

//forces the layout attributes to be recalculated for new data
[collectionView.collectionViewLayout invalidateLayout];

答案 7 :(得分:2)

我遇到了同样的崩溃。

在我的应用程序中,问题是我没有使用UICollectionViewLayoutAttributes清空数组。我在prepareLayout()方法中使用它来存储每个单元格的布局属性。

var itemAttributes: Array<UICollectionViewLayoutAttributes> = Array<UICollectionViewLayoutAttributes>()

在prepareLayout的第一行只有self.itemAttributes.removeAll(),它可以正常工作。

答案 8 :(得分:1)

我能够通过创建UICollectionViewFlowLayout的子类并重写此方法来返回YES来解决此问题:

- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
{
    return YES;
}

答案 9 :(得分:1)

我找到的解决方案是确保我在indexPath方法中创建的layoutAttributesForElementsInRect(rect: CGRect) -> [AnyObject]?对该行有效。以前,我正在使用(i是我的循环计数器):

var indexPath = NSIndexPath(index: i)
var attributes = UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath)

但更新它以使用以下解决了它:

var indexPath = NSIndexPath(forRow: i, inSection: 0)!
var attributes = UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath)

答案 10 :(得分:0)

collectionViewLayout缓存布局属性。 在viewwillappear。创建collectionViewLayout的新实例并将其分配给collectionview.collectionViewLayout 这样,所有缓存的属性都将在重新加载之前清除 您的问题可能已得到解决。为我工作,尤其是在使用其他collectionViewLayout库时。

答案 11 :(得分:0)

我也有这个错误并找到了解决方法。对我来说,UICollectionView是在iOS 7下启动的,完全适用于iOS 8。

查看此文章:What's causing this iOS crash? UICollectionView received layout attributes for a cell with an index path that does not exist

用2个字:自动布局。在包含UICollectionView的视图上禁用它,对我来说,它可以工作。

答案 12 :(得分:0)

我有类似的问题(使用Swift2.0,XCode 7)。

该应用程序与UICollectionView received layout attributes for a cell with an index path that does not exist ...

崩溃

就我而言,由于我使用了故事板,结果发现我忘记将我的viewController中定义的IBOutlet与故事板中定义的实际collectionView连接起来。连接两者解决了问题。

答案 13 :(得分:0)

我已经弄清楚了。 如果您使用nib / xib来组织UITableViewCell和嵌套UICollectionView,则可以通过覆盖此方法来避免此错误。

- (void)prepareForReuse {

    [super prepareForReuse];
    [self.collectionView.collectionViewLayout invalidateLayout];
}

希望它有所帮助。

答案 14 :(得分:0)

  

这意味着dataSouce上没有indexPath(0,2)。但是,您的UICollectionViewLayout为indexPath(0,2)返回UICollectionViewLayoutAttributes。由TopChul

那是对的!对我来说,问题发生是因为我对两个collectionView使用相同的集合布局(实例)!因此,两个集合View之间的布局混淆。

在不同的集合视图之间使用不同的布局后,它工作正常。

答案 15 :(得分:0)

在尝试将集合视图复制到另一个故事板时,我碰到了类似的东西。

  

'UICollectionView接收带索引的单元格的布局属性   不存在的路径:{length = 2,path   = 1 - 0}'

起初,我正在寻找快速解决方案。尝试复制粘贴各种StackOverflow答案。

但我写了自己的布局类。所以我试着谨慎地调试,这可能是我的实施责任,对吧?发现从未调用numberOfSections方法。集合视图假设它只有一个部分。

然后我发现视图控制器类忘记符合UICollectionViewDataSource。尽管dataSource被连接在故事板中,但是视图控制器类可能会被低估,例如if let ds = dataSource as? UICollectionViewDataSource {ds.numberOfSections...},它会无声地失败。

所以我添加了UICollectionViewDataSource的一致性,一切正常。我的猜测可能不准确。但是,经验教训是,每当有一个你不熟悉的错误,安顿下来并理解它。 UICollectionView收到了一个索引路径不存在的单元格的布局属性 ,这正是它所说的内容。不是那么难吗?不要试图找到一个银弹,就像这里的许多答案一样。它们都很棒,但你的代码才是真正的战斗场所。

答案 16 :(得分:0)

我遇到过这个问题而且很烦人。我的解决方法是忘记UICollectionViewController并使用内置UIViewController的常规UICollectionView

答案 17 :(得分:0)

确保您更新contentSize的{​​{1}}。因此,在获取新图像(2而不是5)后,重新计算collectionViewLayout并设置它。

答案 18 :(得分:0)

当我使用UICollectionViewFlowLayout作为CollectionView's collectionViewLayout时遇到同样的问题。

声明已实施viewController的父UICollectionViewDelegateFlowLayout并将其指定为collectionView的委托可以解决此问题。

答案 19 :(得分:0)

就我而言,我有一个自定义UICollectionViewFlowLayout。从collectionView中删除单元后,应用程序崩溃了。解决方法是removeAll()个先前计算的属性。因此,override func prepare()之后的第一行是arrayHoldingYourAttributes.removeAll()

答案 20 :(得分:-2)

Hollo,我在将collectionView插入另一个collectionView和主队列中的reloadData时遇到了同样的问题。最后我在新数据转换为collectionView之前重新加载数据。

dispatch_async(dispatch_get_main_queue(), ^{
    [_collectionView reloadData];
});

_notes = notes;

[_collectionView reloadData];