Il cellForItemAtIndexPath di UICollectionView non viene chiamato


104

È solo la seconda volta che uso UICollectionView e forse ho morso più di quanto posso masticare ma comunque:

Sto implementando un UICollectionView (myCollectionView) che utilizza UICollectionViewCell personalizzati che ho sottoclasse. Le celle sottoclasse (FullReceiptCell) contengono UITableView e hanno le dimensioni del viewcontroller. Sto cercando di consentire lo scorrimento orizzontale tra FullReceiptCells.

L'UICollectionViewController sottoclasse che contiene myCollectionView viene inserito in uno stack del controller di navigazione. Attualmente, loas myCollectionView e lo scorrimento orizzontale sono abilitati. Tuttavia, nessuna cella è visibile. L'ho confermato

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section

è stato eseguito e restituisce un numero intero maggiore di 0. Ho anche confermato che il delegato e l'origine dati di myCollectionView sono impostati correttamente in IB sulla sottoclasse UICollectionViewController.

Il metodo in cui devono essere caricate le celle:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath

non viene chiamato.

Qui è dove inserisco UICollectionViewController e il mio metodo viewDidLoad all'interno di quel controller (NOTA: initWithBill è un override del normale inizializzatore):

Nel precedente file ViewControllers .m:

FullReceiptViewController *test = [[FullReceiptViewController alloc] initWithBill:currentBill];
test.title = @"Review";
[self.navigationController pushViewController:test animated:YES];

In FullReceiptViewController.m:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    [self.myCollectionView registerClass:[FullReceiptCell class] forCellWithReuseIdentifier:@"FullReceiptCellIdentifier"];
    self.myCollectionView.pagingEnabled = YES;
    // Setup flowlayout

    self.myCollectionViewFlowLayout = [[UICollectionViewFlowLayout alloc] init];
    [self.myCollectionViewFlowLayout setItemSize:CGSizeMake(320, 548)];
    [self.myCollectionViewFlowLayout setSectionInset:UIEdgeInsetsMake(0, 0, 0, 0)];
    [self.myCollectionViewFlowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
    self.myCollectionViewFlowLayout.minimumLineSpacing = 0;
    self.myCollectionViewFlowLayout.minimumInteritemSpacing = 0;
    [self.myCollectionView setCollectionViewLayout:myCollectionViewFlowLayout];
    //testing to see if the collection view is loading
    self.myCollectionView.backgroundColor = [UIColor colorWithWhite:0.25f alpha:1.0f];

Qualche indizio sul motivo per cui non viene chiamato?


Sto usando XIB. Non posso rimuovere dalla coda nulla in cellForItemsAtIndexPath perché non viene mai chiamato.
IkegawaTaro

Risposte:


135

Per coloro che inciamperanno qui dopo ... il motivo:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath

non veniva chiamato era perché l'altezza di itemSize per collectionViewFlowLayout era troppo grande.

[self.myCollectionViewFlowLayout setItemSize:CGSizeMake(320, 548)];

Se cambio l'altezza a 410, eseguirà cellForItemAtIndexPath.


Puoi approfondire un po 'di più. Lo stesso sta accadendo per me
user1010819

Ho appena scoperto che devi stare attento anche con collectionViewContentSize
Dimitar Marinov

49
Nel caso in cui utilizzi il layout automatico, assicurati di impostare un vincolo di altezza su collectionView - hai sprecato molte ore su questo!
bpn

per il
limite di

4
Se la tua collectionView è vincolata a topLayoutGuide con AutoLayout e non dovrebbe scorrere sotto NavigationBar, assicurati di deselezionare Adjust Scroll View Insetsil tuo ViewController su Storyboard.
Bruno Galinari

96

Nel mio caso, è stato perché la mia classe di layout è stata sottoclasse erroneamente da UICollectionViewLayoutinvece diUICollectionViewFlowLayout


1
GRAZIE. Perdonami, ci ho passato secoli.
Rambatino

Questo era anche il mio problema! È un po 'controintuitivo, quindi non mi è nemmeno venuto in mente. Grazie per questo!
WendiKidd

Stessa cosa per me! è così facile trascurarlo! grazie ancora
arvidurs

Facepalm qui, grazie per averlo segnalato (4 anni fa).
Milander

Stavo affrontando lo stesso problema. Grazie
Piyush Gupta

31

Il cellForItemAtIndexPath non verrà chiamato se non si forniscono le informazioni sulla dimensione del contenuto alla visualizzazione raccolta.

  1. Se utilizzi il layout Flusso : devi impostare correttamente le dimensioni degli elementi.
  2. Se hai un layout personalizzato sottoclasse da UICollectionViewLayout : assicurati di restituire una dimensione corretta dal metodo collectionViewContentSize.

In quest'ultimo caso, osserverai anche che il tuo layoutAttributesForElementsRect non viene chiamato. Il motivo è che non hai specificato la dimensione del contenuto e per impostazione predefinita la dimensione sarà CGSizeZero. Questo fondamentalmente dice alla vista della raccolta che non hai alcun contenuto da dipingere, quindi non si preoccupa di chiederti attributi o celle.

Quindi, sovrascrivi collectionViewContentSize e fornisci una dimensione adeguata lì, dovrebbe risolvere il tuo problema.


1
Ad esempio, per utilizzare la dimensione completa disponibile, restituisci collectionView.frame.size da collectionViewContentSize (non semplicemente collectionView.contentSize che per impostazione predefinita è 0, 0)
Adam Loving

Grazie! Questa risposta mi ha aiutato b / c ho un UICollectionViewLayout personalizzato. Se ho avviato l'app nel simulatore in orientamento orizzontale, alcune celle non venivano visualizzate nella vista iniziale. L'override della dimensione del contenuto ha risolto questo problema per me.
Chris Livdahl

1
Grazie. Nel mio caso lo collectionViewContentSize0 restituito in modo errato per la larghezza, ecco perché cellForItemAtIndexPathnon è stato chiamato.
izerik

16

Forse lo sto solo trascurando, ma sembra che manchi il delegato e la fonte dati. Nel tuo file di intestazione, assicurati di aver aggiunto questi:

<UICollectionViewDelegate, UICollectionViewDataSource>

e nel tuo metodo viewDidLoad aggiungi questo:

self.myCollectionView.delegate = self;
self.myCollectionView.dataSource = self;

Inoltre, se lo stai caricando tramite un .xib, assicurati di aver connesso IBOutlet a UICollectionView.


1
Non l'ho mostrato ma ho già il delegato e l'origine dati annotati nel file di intestazione. Inoltre, ho collegato IBOutlet a myCollectionView. Il delegato e l'origine dati per questa collectionview sono stati impostati su FullReceiptViewController. La cosa strana è che numberOfItemsInSection (un metodo di protocollo dell'origine dati) viene chiamato e restituisce un numero intero maggiore di 0.
IkegawaTaro

Hmm, quando avvii l'applicazione, la vista Raccolta mostra o fai qualcosa? Sembra che contenga alcuni elementi se numberOfItemsInSection restituisce qualcosa di maggiore di 0.
Anthony Castelli

Grazie per il seguito. La collectionview mostra ... posso dirlo perché ho cambiato il colore di sfondo. Credo di aver trovato il problema: [self.myCollectionViewFlowLayout setItemSize: CGSizeMake (320, 548)]; Questo era troppo grande. Se abbasso l'altezza a 410, posso chiamare il metodo cellForItemAtIndexPath.
IkegawaTaro

@AnthonyCastelli Ciao, sto anche affrontando lo stesso problema, numberOfItemsInSection viene chiamato in pop per viewController ma non cellForItemsAtIndexPath. quindi hai capito?
Bhavin Kansagara

16

Per una gerarchia di visualizzazione più complicata, controlla questo blog . Mi ha salvato la vita!

self.automaticallyAdjustsScrollViewInsets = NO;

1
Ho passato così tanto tempo su questo - e tutto si è ridotto a quello. Se si utilizza lo storyboard o XIB, controllare il controller della vista principale e deselezionare "Regola riquadri della visualizzazione di scorrimento" nell'Ispettore attributi, che è attivato per impostazione predefinita. Ho provato tutte le altre risposte e non hanno funzionato, si è trattato di questo.
etayluz

15

Se la tua classe è una sottoclasse di UICollectionviewController e stai creando collectionView a livello di codice, usa

let layout = UICollectionViewFlowLayout()
    layout.scrollDirection = .Vertical
    layout.itemSize = CGSizeMake(50, 50)

    collectionView?.setCollectionViewLayout(layout, animated: false)

Questa è la risposta che ha risolto il mio problema! Il metodo di sostituzione func collectionView (_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {<# code #>} non funziona per me.
Mike

8

Stavo usando il layout automatico e nel mio caso mancava il vincolo di altezza


6

Il mio problema era che avevo 2 viste della raccolta nella stessa vista ed entrambe condividevano UICollectionViewFlowLayoutun'istanza calcolata . Dopo aver creato istanze separate dello stesso layout di flusso, ha funzionato bene.


5

Nel mio caso, quello che mi ero stupidamente dimenticato di fare era implementare il UICollectionViewDataSourcemetodo del protocollo numberOfItemsInSection, quindi questa è un'altra cosa da controllare.


4

Inoltre, assicurati che reloadData non venga chiamato durante l'aggiornamento della visualizzazione della raccolta con l'animazione (inserisci, elimina, aggiorna o eseguiBatchUpdates).


4

Nel mio caso, il set ha collectionView.prefetchingEnabled = NO;risolto il mio problema. Funziona solo su iOS 10.


2
Ho votato al contrario quella risposta qualche tempo fa e oggi mi ha aiutato di nuovo: D Ti meriti un nobile per questa risposta amico. Grazie ancora!
Maciek Czarnik il

questa risposta ha funzionato per me! Vorrei che ci fosse una spiegazione sul perché incluso in esso perché non l'ho mai impostato su true per cominciare.
Lance Samaria

3

Stava accadendo per me quando l'altezza dell'elemento == 0 fissando quel metodo cellForItem è stato chiamato.


3

Dieci minuti fa ho riscontrato anche questo problema, ho fatto uno stupido errore.

La mia intenzione è utilizzare UICollectionViewFlowLayout,

Ma a causa di errori, ho usato UICollectionViewLayout.


3

Nel mio caso, cambiare la traslucenza di UINavigationBar in NO ha risolto il problema.


3

In Xcode 7.0.1, abbiamo riscontrato questo problema quando abbiamo copiato uno storyboard e il codice di accompagnamento da un altro progetto. La vista della raccolta aveva un layout di flusso personalizzato impostato nello storyboard. La soluzione era:

  • Rimuovere il layout di flusso in IB
  • Compila / esegui l'app
  • Ripristina il layout del flusso

Ora ha funzionato :)


2

Assicurati che numberOfSectionsInCollectionViewrestituisca anche un numero intero positivo.

Deve essere presente almeno una sezione nella raccolta.


2

Assicurati che - (NSInteger) collectionView: numberOfItemsInSection: restituisca un valore positivo (letto, maggiore di zero). Potrebbe essere questione di posizionare [self.collectionView reloadData]; nel gestore di completamento.


2

Ho dimenticato di impostare la maschera di ridimensionamento automatico su false nella vista della raccolta:

collectionView.translatesAutoresizingMaskIntoConstraints = false

2

Possono essere realizzati problemi di layout. Controllare gli avvisi di layout dalla console, se presenti.


2

Nel mio caso la vista della raccolta non era completamente visibile nella sua vista principale a causa di vincoli di layout automatico errati. Quindi la correzione dei vincoli ha reso la vista della raccolta tutta visibile ed è stato chiamato cellForItemAtIndexPath.


2

Nella proprietà storyboard / xib UICollectionView cellSize non DEVE essere {0, 0}


2

Se stai usando i protocolli di visualizzazione della raccolta, devi connettere i protocolli CollectionViewDataSourcee CollectionViewDelegateal tuo ViewController. Prese per la creazione di interfacce


1

Lo stesso è accaduto a me. Avevo 2 UICollectionViews e ho rimosso una volta poiché non ne avevo bisogno. Dopodiché ho capito che CellForItemAtIndexPath non veniva chiamato ma gli altri metodi richiesti. Ho provato tutto quanto sopra ma poi ho fatto la magia standard. Rimossa la vista della raccolta dallo storyboard e aggiunta di nuovo. Poi ha iniziato a funzionare. Non so perché e non ho spiegazioni, ma forse alcuni problemi di connessione.


Ho copiato il mio UICollectionView da un altro UIViewController nello storyboard. Ho eliminato il CollectionView e aggiunto di nuovo per farlo funzionare. La ringrazio per la risposta.
Drunken Daddy

1

Ho appena risolto questo problema, per una situazione un po 'specifica.

Nel mio caso, stavo inizializzando manualmente UICollectionViewController in un ViewController padre e quindi aggiungendo la vista di UICollectionViewController come vista secondaria.

Ho risolto il problema chiamando "setNeedsLayout" e / o "setNeedsDisplay" nella collectionView nella vista del genitoreDidAppear:

- (void)viewDidAppear:(BOOL)animated {
   [super viewDidAppear:animated];
   [_collection.view setNeedsLayout];
   [_collection.view setNeedsDisplay];
}

1

Quando si utilizza UICollectionViewDelegateFlowLayoutfare attenzione a ciò che restituisce questa funzione. Entrambi widthe heightdovrebbero essere maggiori di 0. Ho usato windowcome riferimento del frame ma a causa della complicata finestra della gerarchia di visualizzazione era nilin fase di esecuzione. Se è necessario regolare la larghezza dell'elemento in base all'uso della larghezza dello schermo UIScreen.main.bounds.

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: 
           UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {}

1

Nel mio caso ho avuto la collectionViewin una UIStackViewcon alignment = .center. Quindi collectionViewnon aveva una larghezza. Quando si imposta la stackView.alignmentper .filltutto andava bene.


0

Per me, aggiorno l'altezza di self.view (la superview di collectionView) tramite autolayout e DEVO chiamare layoutIfNeededdopo.

[self.view mas_updateConstraints:^(MASConstraintMaker *make) {
    make.height.equalTo(@(height));
}];
[self.view layoutIfNeeded];

0

Nel mio caso ho dovuto regolare la dimensione del contenuto stimata. dimensione del contenuto non lo ha fatto.

  let layout = collectionVC.collectionView.collectionViewLayout as! UICollectionViewFlowLayout
    layout.itemSize = CGSize(width: 100, height: 100)
    layout.estimatedItemSize = CGSize(width: 100, height: 100)

0

Stavo avendo un problema simile. Ma invece è cellForItemAtIndexPathstato chiamato quando il numero di elementi era> 1, ma non quando c'era un solo elemento. Ho provato molte delle soluzioni proposte qui e simili a molte ho scoperto che aveva a che fare con il dimensionamento degli articoli. Per me la soluzione era cambiare la dimensione della stima UICollectionViewda Automatica a Personalizzata .

Imposta la dimensione stimata su Personalizzata


-1

Ho sprecato un po 'di tempo con questo problema in arrivo con una CollectionView in un controller di visualizzazione contenuto caricato da uno storyboard. Ho finito per eliminare il controller della visualizzazione contenuta e ricrearlo nello storyboard, e questo sembrava eliminare il problema. La mia ipotesi è che si sia verificata una sorta di corruzione dello storyboard.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.