21

Ho bisogno di sapere quando ricaricare un UICollectionView è stato completato per configurare le celle in seguito (perché non sono l'origine dati per le celle - altrimenti sarebbe già stato fatto in altro modo. codice ..)Il ricaricamento di un UICollectionView utilizzando il metodo reloadData ritorna immediatamente prima del ricaricamento dei dati

ho provato come

[self.collectionView reloadData]; 
[self configure cells]; // BOOM! cells are nil 

ho provato anche utilizzando

[self.collectionView performBatchUpdates:^{ 
    [self.collectionView reloadData]; 
    } completion:^(BOOL finished) { 
     // notify that completed and do the configuration now 
    }]; 

ma quando ricaricare il da ta Sto andando in crash.

Come posso ricaricare i dati nella collezione, e solo quando ha finito di ricaricare - fare un particolare gestore di completamento

+0

Penso di aver riscontrato un problema simile. Il problema è che le celle vengono caricate durante layoutSubview che avviene durante il prossimo passaggio del ciclo di esecuzione. Purtroppo non ho ancora trovato la soluzione. mi chiedo perché UICollectionViewDelegate non ha metodi come: - CollectionView: willBeginDisplayingCell: forItemAtIndexPath: mentre c'è: - CollectionView: didEndDisplayingCell: forItemAtIndexPath: avete risolto già che uno? – lukewar

+0

Quello che sta accadendo è che il blocco di aggiornamenti in batch si aspetta che tu faccia chiamate per aggiungere e rimuovere righe/sezioni che corrispondono al nuovo numero di righe e sezioni che si verificano durante il ricaricamento. Se ciò non accade, viene lanciata un'asserzione. –

risposta

81

Questo è causato dalle cellule essere aggiunti durante layoutSubviews non a reloadData. Poiché layoutSubviews viene eseguito durante il prossimo ciclo di esecuzione, dopo il reloadData le celle sono vuote. Prova a fare questo:

[self.collectionView reloadData]; 
[self.collectionView layoutIfNeeded]; 
[self configure cells]; 

ho avuto problema simile e risolto in questo modo.

+12

Grande risposta dovrebbe essere accettata. –

+1

Ho avuto questo problema esatto in cui 'visibleCells' era 0 dopo aver chiamato' -reloadData'. La chiamata '-layoutIfNeeded' ha risolto questo problema. la risposta di lukewar dovrebbe essere accettata. –

+1

Perfetto. Dovrebbe essere accettato –

5

La vista raccolta non è supportata per essere ricaricata animatamente con l'aiuto di reloadData. Tutte le animazioni devono essere eseguite con metodi, come

[collectionView deleteItemsAtIndexPaths:indexesToDelete]; 
[collectionView insertSections:sectionsToInsert]; 
[collectionView reloadItemsAtIndexPaths:fooPaths]; 

interno performBatchUpdates: blocco. Il metodo reloadData può essere utilizzato solo per un aggiornamento approssimativo, quando tutti gli elementi vengono rimossi e disposti di nuovo senza animazione.

+0

Ho avuto una corsa tra tirare per aggiornare e la risposta api e questo ha aiutato. Semplicemente cancellando e inserendo le sezioni che voglio ricaricare invece di reloadData: 'self.collectionView? .performBatchUpdates ({ self.collectionView? .deleteSections (IndexSet (arrayLiteral: 0)) self.collectionView? .insertSections (IndexSet (arrayLiteral : 0)) }, completamento: nil) ' –

4

Se vuoi eseguire un certo codice dopo che il CollectionView ha completato è il metodo reloadData(), quindi provare questo (Swift):

self.collectionView.reloadData() 
    self.collectionView.layoutIfNeeded() 
    dispatch_async(dispatch_get_main_queue()) {() -> Void in 
     // Put the code you want to execute when reloadData is complete in here 
    } 

Il motivo per cui funziona è perché il codice all'interno del blocco di spedizione viene messo in coda (noto anche come coda). Ciò significa che è in attesa in coda che tutte le operazioni del thread principale finiscano, inclusi i metodi di reloadData(), prima che diventi il ​​suo turno sul thread principale.

+1

beh, questo non è completamente vero, il blocco di spedizione può essere inserito tra alcune operazioni di thread principale, vedere http://stackoverflow.com/a/10450867/4003774. Ma il tuo codice funzionerà (anche senza dispatch_async) grazie a layoutIfNeeded (vedi la risposta di @ lukewar) –

Problemi correlati