問題引入
前幾天做專案的時候,發現下面程式碼的響應是異常的:
[collectionView reloadData];
[collectionView selectItemAtIndexPath:indexPath animated:YES scrollPosition:UICollectionViewScrollPositionNone];
複製程式碼
異常在於[collectionView reloadData];
執行正常,把DataSource的變化展現出來了,可是下面的selectItemAtIndexPath
方法卻無響應。目標indexPath對應的item沒有在被選中狀態。
解決方案
後來跟同事討論,發現在執行[collectionView reloadData];
之後,執行selectItemAtIndexPath
方法之前,collectionView的UI並沒有立即做出變化,故selectItemAtIndexPath
是沒有被響應的。
最終能響應的程式碼:
[collectionView reloadData];
[collectionView layoutIfNeeded];
[collectionView selectItemAtIndexPath:indexPath animated:YES scrollPosition:UICollectionViewScrollPositionNone];
複製程式碼
原因
layoutIfNeeded
這個方法和另一個方法配對的,setNeedLayout
和layoutIfNeed
,還有一個關聯的方法是layoutSubviews
,在我們沒有任何干預的情況下,一個view
的fram
或bounds
發生變化時,系統會設定一個flag給這個view,當下一個渲染時機到來時系統會重新按新的佈局來渲染檢視。setNeedLayout
就是我們主動為這個檢視設定一個flag,告訴系統這個檢視再下一個時機到來時要重新渲染,而layoutIfNeed
則是告訴系統,如果設定了flag那麼不用等待時機到來了,直接渲染吧。而layoutSubviews
這個方法是系統呼叫的,我們不需要主動呼叫,我們只需要呼叫layoutIfNeed
就可以了,讓系統判斷是否在當前時機下立即渲染。