UICollectionReusableView-Methode wird nicht aufgerufen

79

Ich möchte, dass meine Abschnitte in der UICollectionVieweinen Header mit einem Bild haben.

Ich habe diese Schritte befolgt:

  • am Storyboard einen Header als Zubehör für meine zugewiesen UICollectionView
  • gab ihm eine Kennung
  • hat eine Unterklasse UICollectionReusableViewdafür erstellt
  • Die benutzerdefinierte Klasse wurde der Klasse im Storyboard zugewiesen.
  • Setzen Sie ein ImageViewam Header-Zubehör
  • machte einen Ausgang für die ImageViewan der benutzerdefinierten Klasse in der .hDatei
  • Implementierte Folgendes bei viewDidLoad:

 

[self.collectionView registerClass:[ScheduleHeaderView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:headerIdentifier];

-(UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
    UICollectionReusableView *reusableview = nil;

    if (kind == UICollectionElementKindSectionHeader)
    {
        ScheduleHeaderView *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:headerIdentifier forIndexPath:indexPath];

        headerView.headerImageView.image = [UIImage imageNamed:@"blah.png"];

        reusableview = headerView;
    }

    return reusableview;
}

Ich weiß, dass die Datenquellen- und Delegatenmethoden funktionieren, da ich alle Zellen und ihre Abschnitte sehen kann. Ich habe jedoch keine Header. Ich habe bei der obigen Methode einen Haltepunkt eingefügt, der nie aufgerufen wird.

Was mache ich falsch?

Eden V.
quelle
3
Beachten Sie, dass Sie die Zeichenfolgenzeiger kind == UICollectionElementKindSectionHeaderanstelle des Inhalts der Zeichenfolgen vergleichen , die Sie wahrscheinlich [kind isEqualToString: UICollectionElementKindSectionHeader]stattdessen verwenden möchten .
Mac_Cain13

Antworten:

199

Es scheint, dass Sie Ihrem Header eine Größe ungleich Null geben müssen oder collectionView:viewForSupplementaryElementOfKind:atIndexPathnicht aufgerufen werden. Stellen Sie also entweder die headerReferenceSizeEigenschaft des Ablauflayouts wie folgt ein:

flowLayout.headerReferenceSize = CGSizeMake(self.collectionView.frame.size.width, 100.f);

Swift 5+

flowLayout.headerReferenceSize = CGSize(CGSize(width: self.collectionView.frame.size.width, height: 100))

oder implementieren collectionView:layout:referenceSizeForHeaderInSectionSie , wenn Sie die Größe nach Abschnitten variieren möchten.

rdelmar
quelle
1
Kann ich in der Sammlungsansicht die dynamische Höhe per Autolayout festlegen, anstatt die Größe von headerReference zu definieren?
Khant Thu Linn
Ist es möglich, headerReferenceSize in Storyboard auf flowLayout festzulegen?
Radek Wilczak
1
Ja, es hat funktioniert! layout.headerReferenceSize = CGSize (width: (self.collectionView? .frame.width)!, height: 50); für swift4
Antony Ouseph
headerReferenceSizefunktioniert, aber ich brauche verschiedene Größen für verschiedene Abschnitte. Und die von Ihnen angegebene Methode wird überhaupt nicht aufgerufen
Vyachaslav Gerchicov
33

Sie haben die Frage beantwortet, aber in Worten verstehe ich besser:

Fügen Sie die folgenden Methoden hinzu, um die aufgerufene Methode zu erstellen:

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section {
    return CGSizeMake(60.0f, 30.0f);
}

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section {
    return CGSizeMake(60.0f, 30.0f);
}

... und geh von dort aus.

Birne Johan
quelle
31

Swift 4 Xcode 9.1 Beta 2

Fügen Sie @objc hinzu

@objc func collectionView(_ collectionView: UICollectionView, layout  collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize{
    let size = CGSize(width: 400, height: 50)
    return size
}

Credits: https://medium.com/@zonble/your-delegation-methods-might-not-be-called-in-swift-3-c6065ed7b4cd

cwilliamsz
quelle
Vielen Dank! Rettete meinen Hintern. Übrigens ist mir aufgefallen, dass diese Funktion nicht in der Liste der automatischen Vervollständigungen für collectionViewDelegate angezeigt wird. Ich weiß nicht warum, so komisch. Auch komisch, dass wir das @ objc-Tag davor brauchen.
C0D3
3
Nur das Hinzufügen von @objc zur Funktion in Swift 4 hat bei mir funktioniert. Lächerlich.
Louis Cremen
7
Die Konformität mit UICollectionViewDelegateFlowLayout anstelle von UICollectionViewDelegate behebt dies auch ohne @objc, wenn Sie UICollectionViewFlowLayout verwenden.
Nemissm
Es ist viel besser, wenn Sie die CollectionView-Grenzen verwenden, um das With Ihrer Abschnittskopf- / Fußzeile festzulegen: let size = CGSize (collectionView.bounds.width, height: 50)
omaestra
18

Haben Sie UICollectionViewDelegateFlowLayout in der aktuellen Benutzeroberfläche hinzugefügt? Das hat bei mir funktioniert.

@interface MyViewController () <UICollectionViewDelegateFlowLayout>

Schnell:

class MyViewController: UICollectionViewDelegateFlowLayout {

CheshireKat
quelle
1
Ahh! Also das ist es ...UICollectionViewDelegateFlowLayout
Ayan Sengupta
8

Swift 3.0 (xcode 8.2.1)

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
    return CGSize(width:collectionView.frame.size.width, height:30.0)
}
Zeeshan
quelle
5

Es gibt die schnelle Version:

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
    let size = CGSize(width: 400, height: 50)
    return size
}

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
    let size = CGSize(width: 400, height: 50)
    return size
}

XCode (Version 7.3.1) schlägt diese Methoden nicht in Autocomplete vor!

Wenn Sie nur einen Header möchten, behalten Sie einfach die Header-Methode bei.

Kevin ABRIOUX
quelle
3
    @objc (collectionView:viewForSupplementaryElementOfKind:atIndexPath:)
    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { }

Der obige Code hat bei mir funktioniert

Bibin Jaimon
quelle
2

Mein Problem war, dass sich in Swift 3 der Name der Funktion viewForSupplementaryElementOfKind gegenüber allen Posts, die sich im Stapelüberlauf befanden, geringfügig geändert hat. Daher wurde es nie angerufen. Stellen Sie sicher, dass Sie, wenn Sie in Swift 3 sind, Funktionsübereinstimmungen delegieren:

func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {}
Daniel Jones
quelle
Meine auch. Für mich fehlte ein "_", "atIndexPath" anstelle von "at" und "NSIndexPath" anstelle von "IndexPath"; da ich die Methode von irgendwoher kopiert habe und IDE mir keinen Fehler gegeben hat.
Ashkan Sarlak
1

Ich habe das gleiche Problem. Ich habe hinzugefügt, referenceSizeForFooterInSectionaber dann auch viewForSupplementaryElementOfKindnicht angerufen. Ich habe diesen Code hinzugefügt viewDidLoad()und es hat bei mir funktioniert:

if let flowLayout = self.collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
    flowLayout.sectionFootersPinToVisibleBounds = true   
}
Funkeln
quelle
0

In Swift 4.2 wurde func collectionView (collectionView: kind: indexPath :) -> UICollectionReusableView nie aufgerufen. Dies war für eine Sammlungsansicht in einem UIViewController. Ich habe festgestellt, dass die vorhandenen Funktionen der Sammlungsansicht mit @objc qualifiziert wurden und dass UICollectionView die Protokolle UICollectionViewDataSource und UICollectionViewDelegate nicht übernommen hat. Sobald ich die Protokolle übernommen habe, wurde die Fehlermeldung angezeigt, dass die Funktionen der Sammlungsansicht nicht mit dem Protokoll übereinstimmen. Ich habe die Funktionssyntax korrigiert, die Qualifikationsmerkmale entfernt und die Abschnittsüberschriften haben funktioniert.

Trishcode
quelle
0

Wenn Sie eine generische Unterklasse haben, müssen Sie darauf achten, den Namen der ObjC-Delegatmethode anzugeben, wenn dieser vom Swift-Namen abweicht ( https://bugs.swift.org/browse/SR-2817 ).

@objc (collectionView:viewForSupplementaryElementOfKind:atIndexPath:)
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
...
Adrian Bilescu
quelle