2013-08-20 33 views
58

在試圖從我的集合視圖中卸載一批圖像然後將其替換爲另一批的過程中,我遇到了一個錯誤,其中取決於原始或後續圖像組是否比預期的更換或多或少,會出現一個斷言錯誤,說:過期數據上的UICollectionView斷言錯誤

*** 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'...

謝謝

+1

它肯定會出現一些陳舊數據的痕跡正在被對象訪問 - 因此搜索一個單元格,其索引可能超出了該部分引用的當前數據的範圍。在我的情況下,經過多次實驗,補救措施似乎是「[self.collectionView reloadSections:sections];」。在我這樣做後,當我向左或向右滑動collectionView時,異常不再被斷言。 – user1686700

+0

我有類似的問題。我有兩個顯示相同數據的UICV。當用戶更改應用程序中的日期時,我請求新數據,然後在兩個CV上調用reloadData。這通過iOS6.1很好。當我運行更新的應用程序時,出現上述錯誤。切換到reloadSections:部分修復它,但添加了不需要的滯後和動畫(自定義流佈局)。你有沒有取得任何進展? – VaporwareWolf

+0

當我返回具有不應存在的索引路徑的佈局屬性時,會根據數據源返回的每個節中的節數和項目數得到此問題!花了我一段時間來弄清楚這一點。如果您有動態模型,請確保節/項目路徑與佈局屬性路徑對齊。 – andrewz

回答

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返回索引路徑(0,2)的UICollectionViewLayoutAttributes。

您應該返回僅存在於dataSouce上的UICollectionViewLayoutAttributes。


我認爲它已從iOS7更改。

+3

你是對的。還必須更新底層數據源/佈局。 –

+0

我的同事上個月發現了另一個案子。 更新contentInsets UICollectionView 將導致更新佈局。 所以,(1)dataSourceChanged,(2)setContentInsets - >與異常崩潰。 (1)dataSourceChanged,(2)reloadData系列(Section,insertXXX等)(3)setContentInsets - > safe。 這種情況可能會遇到iOS 11. – TopChul

83

我在同樣的問題中運行。代碼6.1下運行,並且在7.0 崩潰我解決這個問題的方式如下:

在功能

-(NSInteger) numberOfSectionsInCollectionView:(UICollectionView *)collectionView 

我打電話

[myCollectionView.collectionViewLayout invalidateLayout]; 

That's所有。

+1

謝謝!我知道我必須使佈局失效,但只能用這種方法調用它才能爲我工作。 –

+7

對我來說,它在我調用'reloadData'之前就調用了'invalidateLayout'。 –

+1

任何人都可以解釋爲什麼'invalidateLayout'解決了這個問題嗎? 我試圖更改'dataSource','delegate'和'collectionViewLayout'時遇到同樣的問題。 – alexcristea

0

請確保您更新了您的collectionViewLayoutcontentSize。因此,在獲取新圖像(2,而不是5)後,重新計算contentSize並進行設置。

0

我遇到過這個問題,它很煩人。我的修補程序是忘記UICollectionViewController,並使用UIViewController而不是UICollectionView

4

我通過我的更新集合視圖的數據源解決了這個崩潰:

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

在collectionArray大小更改時調用它,而不是此方法。 –

+0

invalidateLayout不應該在數據源方法中調用 – titaniumdecoy

21

兩個Dominic Sanderuser1544494是正確的,他們的解決方案是好的。

不幸的是,我注意到如果你設置了minimumLineSpacingForSectionAtIndex或者minimumInteritemSpacingForSectionAtIndex,你的collectionView的外觀將會破壞(遲早)。

invalidateLayout放入viewWillLayoutSubviews回答這個問題,有助於保持viewCollection的外觀。

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

我非常喜歡這個解決方案,乾淨而直觀。謝謝! – phatmann

+4

把它放到我的集合視圖控制器後,我有方法'-viewWillLayoutSubviews'被無限調用。視圖層次結構應該如何工作? – igrek

10

我的問題是,我有兩個UICollectionViews裏面一個UIViewController。我有UICollectionViews連接到相同的UICollectionViewLayout子類。我通過更改每個UICollectionView以便擁有自己的UICollectionViewLayout子類來解決此問題。

來源:This Question

+0

你已經救了我的一天,老兄! – Alex

1

我找到的解決方案是爲了確保我在layoutAttributesForElementsInRect(rect: CGRect) -> [AnyObject]?方法中創建的indexPath對該行有效。以前,我使用(其中i是我的循環計數器):

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

但更新它使用下面的解決了這個問題:

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

的collectionViewLayout緩存佈局屬性。 在viewwillappear。創建collectionViewLayout的新實例並將其分配給collectionview.collectionViewLayout 通過這種方式,所有緩存的屬性將在重裝前清除 您的問題可能已解決。爲我工作,尤其是當您使用其他collectionViewLayout庫時。

1

我能夠通過創建UICollectionViewFlowLayout子類,並重寫此方法來解決這個問題,返回YES

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

霍洛,我有同樣的問題,而插入的CollectionView到另一個的CollectionView和reloadData主隊列。最後我重新加載數據之前,一個新的數據轉換爲collectionView。

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

_notes = notes; 

[_collectionView reloadData]; 
2

我有同樣的崩潰。

在我的應用程序中,問題是我沒有用UICollectionViewLayoutAttributes清空數組。我在prepareLayout()方法中使用它來存儲每個單元格的佈局屬性。

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

只需self.itemAttributes.removeAll()在prepareLayout的第一線,它的工作原理。

0

我有類似的問題(使用Swift2.0,XCode 7)。

該應用程序崩潰與UICollectionView received layout attributes for a cell with an index path that does not exist ...

在我的情況,因爲我用故事板,它只是原來,我忘了連接在我的viewController定義與該定義的實際的CollectionView的IBOutlet中故事板。連接兩個固定的問題。

0

我已經想通了。 如果您使用nib/xib組織您的UITableViewCell和嵌套UICollectionView,則可以通過重寫此方法來避免此錯誤。

- (void)prepareForReuse { 

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

希望它有幫助。

0

這意味着dataSouce上沒有indexPath(0,2)。但是,您的UICollectionViewLayout會爲indexPath(0,2)返回一個UICollectionViewLayoutAttributes。 By TopChul

這是正確的!對我而言,問題發生的原因是我使用相同的集合佈局(實例) for two collectionView!這樣兩個集合View之間的佈局混淆了。

在不同的集合視圖之間使用不同的佈局後,它工作正常。

0

當試圖將集合視圖複製到另一個故事板時,我遇到了類似的情況。

'UICollectionView接收用於與索引 路徑的單元不存在的佈局屬性:{長度= 2,路徑 = 1 - 0}'

首先,我尋找快速修復。嘗試複製粘貼各種StackOverflow答案。

但我寫了我自己的佈局類。所以我試圖謹慎調試,這可能是我的實施責怪,對吧?發現numberOfSections方法從未被調用過。收集視圖假定它只有一個部分。

然後我發現視圖控制器類忘記符合UICollectionViewDataSource。雖然dataSource被連接到故事板中,但可能視圖控制器類將被降級,如if let ds = dataSource as? UICollectionViewDataSource {ds.numberOfSections...},這會失敗默默。

所以我添加了符合UICollectionViewDataSource和一切工作正常。我的猜測可能不準確。但是,教訓是,每當有一個你不熟悉的錯誤,安定下來並理解它。 UICollectionView收到一個索引路徑不存在的單元格的佈局屬性,它意味着它說的是什麼。沒那麼難對嗎?不要試圖找到一個銀色的子彈,就像這裏的許多答案。他們都很棒,但你的代碼是真正的戰鬥場所。

2

修改集合視圖的內容後,我遇到過這個問題。在我的情況下工作的解決方案是重新加載後使佈局無效。在重新加載之前執行此操作將不起作用。

[collectionView reloadData]; 

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

隨着iOS的10和11這會有所幫助:

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

佈局無效後應重新加載數據。

+1

也幫助我在iOS 11上 – fruechtemuesli

0

當我使用UICollectionViewFlowLayout作爲CollectionView's collectionViewLayout時遇到同樣的問題。

聲明父viewController實施UICollectionViewDelegateFlowLayout並將其指定爲collectionView的代表可以解決此問題。