Der cellForItemAtIndexPath von UICollectionView wird nicht aufgerufen

104

Erst mein zweites Mal mit UICollectionView und vielleicht habe ich mehr abgebissen, als ich kauen kann, aber trotzdem:

Ich implementiere eine UICollectionView (myCollectionView), die benutzerdefinierte UICollectionViewCell verwendet, die ich in Unterklassen unterteilt habe. Die untergeordneten Zellen (FullReceiptCell) enthalten UITableViews und haben die Größe des Viewcontrollers. Ich versuche, ein horizontales Scrollen zwischen den FullReceiptCells zu ermöglichen.

Der untergeordnete UICollectionViewController, der myCollectionView enthält, wird auf einen Nav-Controller-Stack übertragen. Derzeit ist myCollectionView loas und horizontales Scrollen aktiviert. Es sind jedoch keine Zellen sichtbar. Ich habe das bestätigt

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

wurde ausgeführt und gibt eine Ganzzahl größer als 0 zurück. Ich habe außerdem bestätigt, dass der Delegat und die Datenquelle von myCollectionView in IB ordnungsgemäß auf den untergeordneten UICollectionViewController festgelegt sind.

Die Methode, mit der die Zellen geladen werden sollen:

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

wird nicht aufgerufen.

Hier drücke ich den UICollectionViewController und meine viewDidLoad-Methode in diesen Controller (HINWEIS: initWithBill ist eine Überschreibung des normalen Initialisierers):

In der vorherigen ViewControllers .m-Datei:

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];

Gibt es einen Hinweis darauf, warum es nicht aufgerufen wird?

IkegawaTaro
quelle
Ich benutze XIB. Ich kann nichts in cellForItemsAtIndexPath aus der Warteschlange entfernen, da es nie aufgerufen wird.
IkegawaTaro

Antworten:

135

Für diejenigen, die später hier stolpern .... der Grund:

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

wurde nicht aufgerufen, weil die itemSize für die collectionViewFlowLayout-Höhe zu groß war.

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

Wenn ich die Höhe auf 410 ändere, wird cellForItemAtIndexPath ausgeführt.

IkegawaTaro
quelle
Können Sie etwas näher darauf eingehen? Gleiches passiert für mich
user1010819
Ich habe gerade festgestellt, dass Sie auch mit collectionViewContentSize vorsichtig sein müssen
Dimitar Marinov
49
Wenn Sie Autolayout verwenden - stellen Sie sicher, dass Sie in der collectionView eine Höhenbeschränkung festlegen -, verschwenden Sie viele Stunden damit!
Bpn
für die Rekordhöhenbeschränkung hat bei mir nicht funktioniert. Horizontale Mittelbeschränkungen haben es geschafft
Mohamed Emad Hegab
4
Wenn Ihre collectionView mit AutoLayout auf topLayoutGuide beschränkt ist und nicht unter NavigationBar scrollen soll, deaktivieren Sie Adjust Scroll View InsetsIhr ViewController im Storyboard.
Bruno Galinari
96

In meinem Fall lag es daran, dass meine Layoutklasse fälschlicherweise von UICollectionViewLayoutstatt klassifiziert wurdeUICollectionViewFlowLayout

Silber
quelle
1
DANKE. Verdammt, ich habe ewig damit verbracht.
Rambatino
Das war auch mein Problem! Es ist ein wenig eingängig, also ist es mir nicht einmal in den Sinn gekommen. Danke dafür!
WendiKidd
Auch für mich! es ist so leicht zu übersehen!
Nochmals vielen
Facepalm hier, danke, dass Sie darauf hingewiesen haben (vor 4 Jahren).
Milander
Ich stand vor dem gleichen Problem. Vielen Dank
Piyush Gupta
31

Der cellForItemAtIndexPath wird nicht aufgerufen, wenn Sie der Sammlungsansicht keine Informationen zur Inhaltsgröße bereitstellen.

  1. Wenn Sie das Flow-Layout verwenden : Sie müssen die Artikelgrößen richtig einstellen.
  2. Wenn Sie ein benutzerdefiniertes Layout haben, das von UICollectionViewLayout untergeordnet ist : Stellen Sie sicher, dass Sie eine korrekte Größe von der collectionViewContentSize-Methode zurückgeben.

In letzterem Fall werden Sie auch feststellen , dass Ihr layoutAttributesForElementsRect ebenfalls nicht aufgerufen wird. Der Grund dafür ist, dass Sie nicht angegeben haben, wie groß Ihr Inhalt ist, und dass die Größe standardmäßig CGSizeZero ist. Dies teilt der Sammlungsansicht im Grunde mit, dass Sie keinen Inhalt zum Malen haben, sodass Sie nicht nach Attributen oder Zellen gefragt werden müssen.

Überschreiben Sie also einfach collectionViewContentSize und geben Sie dort die richtige Größe an. Dies sollte Ihr Problem lösen.

Deepak GM
quelle
1
Um beispielsweise die volle verfügbare Größe zu verwenden, geben Sie collectionView.frame.size von collectionViewContentSize zurück (nicht einfach collectionView.contentSize, die standardmäßig 0, 0 ist)
Adam Loving
Vielen Dank! Diese Antwort hat mir geholfen, weil ich ein benutzerdefiniertes UICollectionViewLayout habe. Wenn ich die App im Simulator im Querformat gestartet habe, wurden einige Zellen in der Anfangsansicht nicht angezeigt. Das Überschreiben der Inhaltsgröße hat dieses Problem für mich behoben.
Chris Livdahl
1
Danke dir. In meinem Fall hat die collectionViewContentSizefalsch 0 für die Breite zurückgegeben, deshalb cellForItemAtIndexPathwurde die nicht aufgerufen.
Izerik
16

Vielleicht übersehe ich es nur, aber es scheint, dass Sie Ihren Delegierten und Ihre Datenquelle vermissen. Stellen Sie in Ihrer Header-Datei sicher, dass Sie Folgendes hinzugefügt haben:

<UICollectionViewDelegate, UICollectionViewDataSource>

Fügen Sie in Ihrer viewDidLoad-Methode Folgendes hinzu:

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

Wenn Sie es über eine .xib laden, stellen Sie außerdem sicher, dass Sie das IBOutlet mit der UICollectionView verbunden haben.

Anthony Castelli
quelle
1
Ich habe es nicht angezeigt, aber ich habe den Delegaten und die Datenquelle bereits in der Header-Datei vermerkt. Zusätzlich habe ich das IBOutlet mit myCollectionView verbunden. Der Delegat und die Datenquelle für diese Sammlungsansicht wurden auf FullReceiptViewController festgelegt. Das Seltsame ist, dass numberOfItemsInSection (eine Datenquellenprotokollmethode) aufgerufen wird und eine Ganzzahl größer als 0
zurückgibt
Hmm, wird beim Starten der Anwendung in der Sammlungsansicht etwas angezeigt oder ausgeführt? Es klingt so, als ob es einige Elemente enthält, wenn numberOfItemsInSection etwas größer als 0 zurückgibt.
Anthony Castelli
Vielen Dank für das Follow-up. Die Sammlungsansicht zeigt ... Ich kann es erkennen, weil ich die Hintergrundfarbe geändert habe. Ich glaube, ich habe das Problem gefunden: [self.myCollectionViewFlowLayout setItemSize: CGSizeMake (320, 548)]; Das war zu groß. Wenn ich die Höhe auf 410 reduziere, kann ich die aufzurufende cellForItemAtIndexPath-Methode erhalten.
IkegawaTaro
@AnthonyCastelli Hallo, ich habe auch das gleiche Problem: numberOfItemsInSection wird beim Öffnen von pop to viewController aufgerufen, nicht jedoch bei cellForItemsAtIndexPath. Verstehst du den Hinweis?
Bhavin Kansagara
16

Für eine kompliziertere Ansichtshierarchie überprüfen Sie bitte diesen Blog . Es hat mein Leben gerettet!

self.automaticallyAdjustsScrollViewInsets = NO;
Jaybo
quelle
1
Ich habe so viel Zeit damit verbracht - und darauf kam es an. Wenn Sie Storyboard oder XIB verwenden, sehen Sie sich den übergeordneten Ansichtscontroller an und deaktivieren Sie im Attributinspektor die Option "Bildlaufansichten anpassen", die standardmäßig aktiviert ist. Ich habe alle anderen Antworten ausprobiert und sie haben nicht funktioniert, es kam darauf an.
Etayluz
15

Wenn Ihre Klasse eine Unterklasse von UICollectionviewController ist und Sie collectionView programmgesteuert erstellen, verwenden Sie

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

    collectionView?.setCollectionViewLayout(layout, animated: false)
Gurjinder Singh
quelle
Dies ist die Antwort, die mein Problem gelöst hat! Die Überschreibungsmethode func collectionView (_ collectionView: UICollectionView, Layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {<# code #>} funktioniert bei mir nicht.
Mike
8

Ich habe Autolayout verwendet und in meinem Fall fehlte die Höhenbeschränkung

AamirR
quelle
6

Mein Problem war, dass ich zwei Sammlungsansichten in derselben Ansicht hatte und beide eine berechnete UICollectionViewFlowLayoutInstanz gemeinsam nutzten . Nachdem ich separate Instanzen desselben Ablauflayouts erstellt hatte, funktionierte dies einwandfrei.

Nebyark
quelle
5

In meinem Fall hatte ich sehr dumm vergessen, die UICollectionViewDataSourceProtokollmethode zu implementieren numberOfItemsInSection, also ist das eine andere Sache, die überprüft werden muss.

Dean
quelle
4

Stellen Sie außerdem sicher, dass reloadData nicht aufgerufen wird, während die Sammlungsansicht mit Animation aktualisiert wird (Einfügen, Löschen, Aktualisieren oder Durchführen von BatchUpdates).

sasha_nec
quelle
4

In meinem Fall hat set collectionView.prefetchingEnabled = NO;mein Problem gelöst. Funktioniert nur unter iOS 10.

6david9
quelle
1
Ich habe diese Antwort vor einiger Zeit positiv bewertet und heute hat sie mir wieder geholfen: D Sie verdienen einen Noble für diesen Antwortmann. Danke noch einmal!
Maciek Czarnik
Diese Antwort hat bei mir funktioniert! Ich wünschte, es gäbe eine Erklärung dafür, warum dies enthalten ist, weil ich es von Anfang an nie auf wahr gesetzt hatte.
Lance Samaria
3

Es passierte für mich, als die Elementhöhe == 0 war, indem die cellForItem-Methode aufgerufen wurde.

Jirune
quelle
3

Vor zehn Minuten bin ich auch auf dieses Problem gestoßen, ich habe einen dummen Fehler gemacht.

Meine Absicht ist es, UICollectionViewFlowLayout zu verwenden.

Aber wegen Fehlern habe ich UICollectionViewLayout verwendet.

Vincent Sit
quelle
3

In meinem Fall wurde das Problem durch Ändern der durchscheinenden UINavigationBar in NO gelöst.

Chanil
quelle
3

In Xcode 7.0.1 trat dieses Problem auf, als wir ein Storyboard und den zugehörigen Code aus einem anderen Projekt kopierten. In der Sammlungsansicht wurde im Storyboard ein benutzerdefiniertes Ablauflayout festgelegt. Die Lösung war:

  • Entfernen Sie das Flusslayout in IB
  • Kompilieren Sie die App und führen Sie sie aus
  • Stellen Sie das Ablauflayout zurück

Jetzt hat es funktioniert :)

Bart van Kuik
quelle
2

Stellen Sie sicher, dass auch numberOfSectionsInCollectionVieweine positive Ganzzahl zurückgegeben wird.

Es muss mindestens einen Abschnitt in der Sammlung geben.

Eran Goldin
quelle
2

Stellen Sie sicher, dass - (NSInteger) collectionView: numberOfItemsInSection: einen positiven Wert (read, größer als Null) zurückgibt. Möglicherweise müssen Sie [self.collectionView reloadData] platzieren. im Completion Handler.

RT Denver
quelle
2

Ich habe vergessen, die Autoresizing-Maske in der Sammlungsansicht auf false zu setzen:

collectionView.translatesAutoresizingMaskIntoConstraints = false
Stritt
quelle
2

Es können Layoutprobleme realisiert werden. Überprüfen Sie die Layoutwarnungen von der Konsole, falls vorhanden.

erdikanik
quelle
2

In meinem Fall war die Sammlungsansicht in der übergeordneten Ansicht aufgrund falscher Einschränkungen für das automatische Layout nicht vollständig sichtbar. Durch das Korrigieren der Einschränkungen wurde die Sammlungsansicht sichtbar und cellForItemAtIndexPath wurde aufgerufen.

Khaled Annajar
quelle
2

In der Storyboard / xib-UICollectionView-Eigenschaft darf cellSize nicht {0, 0} sein.

poGUIst
quelle
2

Wenn Sie Protokolle für die Sammlungsansicht verwenden, müssen Sie die Protokolle CollectionViewDataSourceund CollectionViewDelegatemit Ihrem ViewController verbinden. Interface Builder-Steckdosen

Declan McKenna
quelle
1

Das gleiche ist mir passiert. Ich hatte 2 UICollectionViews und habe sie einmal entfernt, da ich das nicht brauchte. Danach wurde mir klar, dass der CellForItemAtIndexPath nicht aufgerufen wurde, sondern die anderen erforderlichen Methoden. Ich habe all das versucht, aber dann habe ich die Standardmagie gemacht. Die Sammlungsansicht wurde aus dem Storyboard entfernt und erneut hinzugefügt. Dann fing es an zu arbeiten. Ich weiß nicht warum und ich habe keine Erklärung, aber vielleicht einige Verbindungsprobleme.

Hafeez
quelle
Ich habe meine UICollectionView von einem anderen UIViewController im Storyboard kopiert. Ich habe die CollectionView gelöscht und erneut hinzugefügt, damit sie funktioniert. Vielen Dank für Ihre Antwort.
Betrunkener Papa
1

Dieses Problem wurde gerade für eine bestimmte Situation behoben.

In meinem Fall habe ich den UICollectionViewController in einem übergeordneten ViewController manuell initialisiert und dann die Ansicht des UICollectionViewController als Unteransicht hinzugefügt.

Ich habe das Problem behoben, indem ich 'setNeedsLayout' und / oder 'setNeedsDisplay' in der collectionView in der viewDidAppear des Elternteils aufgerufen habe:

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

Achten Sie bei der Verwendung UICollectionViewDelegateFlowLayoutdarauf, was diese Funktion zurückgibt. Beides widthund heightsollte größer sein als 0. Ich habe windowals Rahmenreferenz verwendet, aber aufgrund der komplizierten Ansichtshierarchie war das Fenster nilzur Laufzeit. Wenn Sie die Breite des Elements basierend auf der Bildschirmbreite anpassen müssen, verwenden Sie UIScreen.main.bounds.

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

Für mich aktualisiere ich die Höhe von self.view (die Übersicht von collectionView) über Autolayout und MUSS danach aufrufen layoutIfNeeded.

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

In meinem Fall musste ich die geschätzte Inhaltsgröße anpassen. Inhaltsgröße hat es nicht getan.

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

Ich hatte ein ähnliches Problem. Aber stattdessen cellForItemAtIndexPathwurde aufgerufen, wenn die Anzahl der Elemente> 1 war, aber nicht, wenn es nur ein einzelnes Element gab. Ich habe viele der hier vorgeschlagenen Lösungen ausprobiert und ähnlich wie bei vielen anderen festgestellt, dass dies mit der Größe der Artikel zu tun hat. Für mich bestand die Lösung darin, die geschätzte Größe von UICollectionViewvon Automatisch auf Benutzerdefiniert zu ändern .

Setzen Sie die geschätzte Größe auf Benutzerdefiniert

Wouter
quelle
0

In meinem Fall hatte ich das collectionViewin einem UIStackViewmit alignment = .center. Das collectionViewhatte also keine Breite. Wenn die Einstellung stackView.alignmentauf .fillalles war in Ordnung.

Nico S.
quelle
-1

Ich habe ein wenig Zeit damit verbracht, dass dieses Problem mit einer CollectionView in einem Contained View-Controller auftritt, der aus einem Storyboard geladen wurde. Am Ende habe ich nur den enthaltenen View Controller gelöscht und im Storyboard neu erstellt, und dies schien das Problem zu beseitigen. Ich vermute, es gab eine Art Storyboard-Korruption, die stattgefunden hatte.

wfbarksdale
quelle