CollectionView sizeForItemAtIndexPath wurde nie aufgerufen

91

Das macht mich verrückt! Ich habe einen UICollectionViewController wie unten gezeigt:

class PhrasesCompactCollectionViewController: UICollectionViewController

Die Anzahl der Abschnitte und cellForItemAt werden aufgerufen, aber der sizeForItemAtIndexPath wird niemals aufgerufen. Ich verwende den gleichen exakten Code woanders und er wird korrekt ausgelöst. Ich benutze Xcode 8 Beta 6.

func collectionView(collectionView: UICollectionView,
                        layout collectionViewLayout: UICollectionViewLayout,
                        sizeForItemAtIndexPath indexPath:  NSIndexPath) -> CGSize {

        return CGSize(width: 120, height:120) 
    }
John Doe
quelle

Antworten:

249

Sie müssen angeben, dass Sie das Protokoll UICollectionViewDelegateFlowLayoutin Ihrer Klassendeklaration implementieren .

class PhrasesCompactCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout

Almas
quelle
10
Ich habe das getan, aber es heißt immer noch nicht. :(
Van Du Tran
57

In Swift 3+ Verwenden Sie diese Methode:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width:(collectionView.frame.height-90)/2, height: 100)
}

Stellen Sie sicher, dass Ihre Klasse beiden Delegierten entspricht

  • UICollectionViewDelegate

  • UICollectionViewDelegateFlowLayout

Shiv Kumar
quelle
4
Die Einhaltung ist redundant, UICollectionViewDelegatewie dies UICollectionViewController bereits tut.
Van Du Tran
2
@ VanDuTran Es ist nicht redundant zu sagen, dass es erforderlich ist, weil es nicht erforderlich ist, ein UICollectionViewController zu sein ...
Michael Hudson
Ich denke, Sie haben gemeint, dass Viewcontroller, eine Ansicht ohne Sammlung, das UICollectionViewDelegate sein kann.
ScottyBlades
1
UICollectionViewDelegateFlowLayout erbt von UICollectionViewDelegate. Implementieren Sie also einfach das UICollectionViewDelegateFlowLayout
evya
43

Ich hatte das gleiche Problem. Das einzige, was mir geholfen hat, war, die 'Geschätzte Größe' für die Zellengröße unter dem Sammlungsgrößeninspektor 'Keine' zu erstellen.

Geben Sie hier die Bildbeschreibung ein

Zenman C.
quelle
8
Du hast meinen Tag gerettet, Kumpel, du bist ein Held
Asif Ali
1
Irgendwie haben alle anderen Antworten auf alle anderen Beiträge über die Verwendung dies sizeForItemAtnicht erwähnt. Sehr hilfreich.
JCutting8
Das ist verrückt!!!! Ich habe auf dem iPhone 5 Simulator mit 10.3.1 iOS Version getestet und die Methode wird aufgerufen. auf iPhone 5s Simulator mit 10.3.1 Versionsmethode wird nicht aufgerufen !!! Ich habe die geschätzte Größe in Keine geändert. Es wurde auf dem iPhone 5s aufgerufen. WT WT WT
hasan
Vielen Dank! Meine Sammlungsansicht mit benutzerdefinierten Funktionen sizeForItemAtfunktionierte gut bis Xcode 11.4, als die Zellen plötzlich eine falsche Breite hatten. Versuchte ein paar Dinge und das hat endlich funktioniert.
Filip
Du hast meine Zeit gespart. Vielen Dank.
Shahbaz Akram
15

Swift 3

Um die Zellengröße von UICollectionView festzulegen, müssen Sie ein Objekt von erstellen und anpassen UICollectionViewFlowLayout . Passen Sie die Eigenschaften an und setzen Sie das Layoutobjekt auf das UICollectionView-Objekt.

Ändern Sie die Objekte cellheight und cell cellWidth entsprechend Ihren Anforderungen (die gewünschte Zellenhöhe und -breite).

override func viewDidLoad() {
    super.viewDidLoad()

    let cellWidth : CGFloat = myCollectionView.frame.size.width / 4.0
    let cellheight : CGFloat = myCollectionView.frame.size.height - 2.0
    let cellSize = CGSize(width: cellWidth , height:cellheight)

    let layout = UICollectionViewFlowLayout()
    layout.scrollDirection = .vertical //.horizontal
    layout.itemSize = cellSize
    layout.sectionInset = UIEdgeInsets(top: 1, left: 1, bottom: 1, right: 1)
    layout.minimumLineSpacing = 1.0
    layout.minimumInteritemSpacing = 1.0
    myCollectionView.setCollectionViewLayout(layout, animated: true)

    myCollectionView.reloadData()
}

Stellen Sie sicher: Wenn Sie die Methode sizeForItemAt indexPath hinzugefügt haben, müssen Sie die Methode ENTFERNEN ...

Untere Methode entfernen

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

}
Gaurav Rami
quelle
12
Wie ist das hilfreich?
Almas
1
Almas, dies ist hilfreich, um die benutzerdefinierte Zellengröße von UICollectionViewCell festzulegen. Es gibt die Variablen cellWidth und cellHeight, in denen Sie Ihre eigenen Werte definieren können ... sowie "layout.sectionInset", "layout.minimumLineSpacing" und "layout" .minimumInteritemSpacing ", diese Variablen sind auch für die UICollectionViewCell-Größe von Bedeutung.
Gaurav Rami
2
Dies funktioniert nur, wenn alle Zellen gleich groß sind. Die folgende Antwort ist die richtige Antwort
JeffN
Dies dient zum Ändern der Größe der UICollectionView, jedoch nicht der Zelle in der Ansicht
Async
Dies ist keine Antwort darauf, warum die Delegatenmethode nicht aufgerufen wird
Ziv Kesten
9

Swift 5

Alle diese Schritte sind erforderlich :

  1. Konform mit UICollectionViewDelegateFlowLayout <== Absolut erforderlich !!
  2. und zu UICollectionViewDelegate, UICollectionViewDataSource
  3. Legen Sie diese in viewDidLoad: collectionView.delegate = selfund festcollectionView.dataSource = self
  4. Setzen Sie die geschätzte Größe im Interface Builder auf Keine
  5. Stellen Sie sicher, dass die folgende Methode sizeForItemAt und nicht sizeForItemAtIndexPath hat

wie :

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
{
    return CGSize(width: 100, height:100)
} 
Xys
quelle
1
Schätzung der Größe auf Keine - rette meinen Tag!
Joe Hallenbeck
6

Die erste Klasse muss UICollectionViewDelegateFlowLayout bestätigen. Dann müssen Sie folgenden Code in viewDidLoad () schreiben:

// Um ​​die UICollectionView anzuweisen, die UICollectionViewDelegateFlowLayout-Methoden Ihres UIViewControllers zu verwenden

collectionView.delegate = self

// Wenn Sie Ihr eigenes Ablauflayout für die Sammlungsansicht festlegen möchten

let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical //depending upon direction of collection view

self.collectionView?.setCollectionViewLayout(layout, animated: true)

Mit diesem Code UICollectionViewDelegateFlowLayout-Methode

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

wird aufgerufen, können Sie die Größe in dieser Methode einstellen.

HS Progr
quelle
4

Drei Dinge, die Sie überprüfen müssen, wenn keine Antwort funktioniert:

  1. Implementieren Sie den FlowLayout-Delegaten: class MyController: UICollectionViewController, UICollectionViewDelegateFlowLayout

  2. Verwenden Sie die Methode für die Größe des Artikels für Swift 3.0+: func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return CGSize(width: (collectionView.frame.width / 3) - 1, height: collectionView.frame.width) }

  3. Wählen Sie Estimate size = Noneim Inspect-Element von UICollectionView.

Manish
quelle
2

Ich hatte das gleiche Problem und nichts würde es beheben. Ich hatte eine gelbe Warnung mit der Aufschrift, es privat zu machen, weil es einer anderen vom Layout-Delegierten definierten Funktion nahe kam. Was es für mich behoben hat war:

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

Beachten Sie den Unterschied zwischen "sizeForItemAtIndexPath" und der richtigen "sizeForItemAt".

Ich riss mir tagelang die Haare aus, um das herauszufinden, und es funktionierte schließlich. Im Folgenden werde ich alle meine Funktionen einschließen, um Ihnen zu zeigen, wie ich auch eine Zelle "versteckt" habe, indem ich die Höhe gleich 0 gemacht habe.

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let findIndex = labelArray.index(of: "\(labelArray[indexPath.row])")
    let screenSize = UIScreen.main.bounds
    let screenWidth = screenSize.width

    if (findIndex! % 2 == 0){
        // Even index, show cell
        return CGSize(width: screenWidth, height: 246)
    }
    else {
        return CGSize(width: screenWidth, height: 0)
    }
}
Stephen Rains
quelle
0

Ich hatte dieses Problem letzte Nacht. Endlich um Mitternacht gelöst, als mir klar wurde, dass die Methode 'didSelectItemAtIndex' nicht mit einer Verschlussklammer "}" abgeschlossen wurde.

Ich habe eine Abschlussklammer ganz unten in der Klasse hinzugefügt, als ich nach dem Kompilierungsfehler gefragt wurde. Tatsächlich befanden sich alle Methoden unter 'didSelectItemAtIndex' in dieser Methode.

Hier posten, nur für den Fall, dass jemand anderes 4 Stunden seines Abends damit verschwendet :-(

Charlie Seligman
quelle
0

Stellen Sie sicher, dass Sie dies in viewDidLoad () einfügen.

collectionView.delegate = self
Azam
quelle
0

Mein Problem war, dass ich mein UICollectionViewDataSource-Objekt als lokale Variable erstellen ließ. Wenn Sie Ihr dataSource-Objekt also manuell im Code initialisieren, müssen Sie es als globale Variable speichern.

Petro Darchyn
quelle
0

Verwenden Sie diese Methode

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

}

Anstatt

private func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {

}
Abdul Malik Aman
quelle
-11

Für mich (in Swift 3.1) muss die Methode wie folgt als öffentlich deklariert werden:

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

Vergiss nicht, es öffentlich zu machen .

Oliver Eichhorn
quelle
publicMit diesem Code können Sie Ihren Code zwischen Frameworks und Modulen zugänglich machen.
ScottyBlades