UICollectionView sembra avere un comportamento speciale (un bug?): Se ha bisogno di layout, performBatchUpdates:
funziona come un reloadData
prima di chiamare il blocco di aggiornamento, che esegue il rendering delle modifiche che si intendono apportare durante il blocco di aggiornamento alla raccolta. guarda la contabilità
Se si prevede di avere gli aggiornamenti batch applicate alla vista prima che sia stato correttamente disposto (come da un gestore di notifica in un ambiente in rapida evoluzione del modello di dati, per esempio), è necessario fare in modo che in viewWillAppear:
che chiamate layoutIfNeeded
sulla vista collezione. Ciò impedirà il recupero della vista di raccolta nella chiamata a performBatchUpdates:
.
Abbiamo scoperto questo comportamento mettendo un registro nella nostra vista origine dati di raccolta numberOfSections
metodo e stampate questo backtrace per vedere dove è stato chiamato da:
2014-11-12 15:30:06.173 CVCrasher[66830:6387719] [CV] #sections stack: (
0 CVCrasher 0x000000010ba9122d -[MyViewController numberOfSectionsInCollectionView:] + 61
1 UIKit 0x000000010cfc2811 -[UICollectionViewData _updateItemCounts] + 147
2 UIKit 0x000000010cfc4a89 -[UICollectionViewData numberOfSections] + 22
3 UIKit 0x000000010cfaebae -[UICollectionViewFlowLayout _getSizingInfos] + 348
4 UIKit 0x000000010cfafca9 -[UICollectionViewFlowLayout _fetchItemsInfoForRect:] + 526
5 UIKit 0x000000010cfab51f -[UICollectionViewFlowLayout prepareLayout] + 257
6 UIKit 0x000000010cfc2a10 -[UICollectionViewData _prepareToLoadData] + 67
7 UIKit 0x000000010cfc30e9 -[UICollectionViewData validateLayoutInRect:] + 54
8 UIKit 0x000000010cf8b7b8 -[UICollectionView layoutSubviews] + 170
9 UIKit 0x000000010c9d1973 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 521
10 QuartzCore 0x0000000110cf2de8 -[CALayer layoutSublayers] + 150
11 QuartzCore 0x0000000110ce7a0e _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 380
12 UIKit 0x000000010c9c5847 -[UIView(Hierarchy) layoutBelowIfNeeded] + 611
13 UIKit 0x000000010cf9c7b7 -[UICollectionView performBatchUpdates:completion:] + 164
...
Qui si può vedere chiaramente che la chiamata a performBatchUpdates:
sta colpendo l'origine dati e diventando coerente con il modello modificato prima dello gli aggiornamenti vengono applicati. Quando viene chiamato il blocco stesso, la vista dell'insieme lancia un assert come ho mostrato nella domanda originale.
tl; dr - Quando UICollectionView bisogno di layout, performBatchUpdates:
agisce efficacemente come una chiamata alla reloadData
e renderà il blocco asserzione aggiornamento batch causa del cattivo contabilità. Chiama layoutIfNeeded
in viewWillAppear:
per evitare questo comportamento.
fonte
2014-11-12 23:58:29
Significa richiamare 'layoutIfNeeded' in' viewWillAppear: 'e chiamare' performBatchUpdates: 'successivamente in' viewDidAppear: '? Quindi quando chiamate 'performBatchUpdates:' in 'viewDidAppear:', UICollectionView controllerà di trovarlo senza bisogno di fare di nuovo il layout e non chiamerà 'reloadData'? –
Questo bizzarro errore ha richiesto più di un giorno per risolverlo. Grazie per la tua risposta, mi ha indirizzato nella giusta direzione. Fare 'layoutIfNeeded' in' viewWillAppear' non funziona per noi perché gli aggiornamenti iniziano anche prima - ma facendo un 'layoutIfNeeded' proprio prima che il nostro modello di dati lo aggiorni! Questo dovrebbe essere sicuramente classificato come un bug per Apple.Se decidono di eseguire 'reloadData' invece degli aggiornamenti batch, devono eliminare il blocco di aggiornamento batch per evitare incongruenze. – Accatyyc