Metoda UICollectionReusableView nie jest wywoływana

79

Chcę, aby moje sekcje UICollectionViewmiały nagłówek z obrazem.

Wykonałem następujące kroki:

  • w scenorysie przypisano nagłówek jako dodatek do mojego UICollectionView
  • nadał mu identyfikator
  • utworzył UICollectionReusableViewdla niego podklasę
  • przypisał klasę niestandardową do klasy w scenorysie.
  • umieścić ImageViewna akcesorium nagłówka
  • stworzył ujście dla ImageViewklasy niestandardowej w .hpliku
  • Wdrożono w 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;
}

Wiem, że metody źródła danych i delegata działają, ponieważ widzę wszystkie komórki i ich sekcje. Jednak nie mam swoich nagłówków. W powyższej metodzie wstawiłem punkt przerwania i nigdy nie jest on wywoływany.

Co ja robię źle?

Eden V.
źródło
3
Zauważ, że porównujesz wskaźniki kind == UICollectionElementKindSectionHeaderdo ciągów zamiast zawartości łańcuchów, prawdopodobnie chcesz użyć [kind isEqualToString: UICollectionElementKindSectionHeader]zamiast tego.
Mac_Cain13

Odpowiedzi:

200

Wygląda na to, że musisz nadać nagłówkowi niezerowy rozmiar lub collectionView:viewForSupplementaryElementOfKind:atIndexPathnie jest wywoływany. Więc albo ustaw headerReferenceSizewłaściwość układu przepływu w następujący sposób:

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

Swift 5+

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

lub zastosuj, collectionView:layout:referenceSizeForHeaderInSectionjeśli chcesz zmieniać rozmiar według sekcji.

rdelmar
źródło
1
w widoku kolekcji, czy mogę zrobić dla dynamicznej wysokości przez autolayout zamiast definiować rozmiar headerReference?
Khant Thu Linn
czy można ustawić headerReferenceSize w Storyboard na flowLayout?
Radek Wilczak
1
Tak, zadziałało! layout.headerReferenceSize = CGSize (width: (self.collectionView? .frame.width) !, height: 50); dla swift4
Antony Ouseph
headerReferenceSizedziała, ale potrzebuję różnych rozmiarów dla różnych sekcji. A metoda, którą podałeś, nie jest w ogóle wywoływana
Vyachaslav Gerchicov,
33

Odpowiedziałeś na pytanie, ale słowami rozumiem lepiej:

Aby wywołać metodę, dodaj następujące metody:

- (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);
}

... i idź stamtąd.

Gruszka Johan
źródło
31

Swift 4 Xcode 9.1 Beta 2

Dodaj @objc

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

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

cwilliamsz
źródło
Dziękuję Ci! Uratowałem mój tyłek. Przy okazji zauważyłem, że ta funkcja nie pojawia się na liście autouzupełniania dla collectionViewDelegate. Nie wiem dlaczego, takie dziwne. Dziwne jest również to, że potrzebujemy przed nim tagu @objc.
C0D3
3
Tylko dodanie @objc do funkcji w Swift 4 zadziałało dla mnie. Śmieszny.
Louis Cremen
7
Zgodność z UICollectionViewDelegateFlowLayout zamiast UICollectionViewDelegate również rozwiązuje ten problem bez @objc, jeśli używasz UICollectionViewFlowLayout.
nemissm
o wiele lepiej, jeśli użyjesz granic collectionView do ustawienia z nagłówka / stopki sekcji: let size = CGSize (collectionView.bounds.width, height: 50)
omaestra
18

Czy dodałeś UICollectionViewDelegateFlowLayout w bieżącym interfejsie? To zadziałało dla mnie.

@interface MyViewController () <UICollectionViewDelegateFlowLayout>

Szybki:

class MyViewController: UICollectionViewDelegateFlowLayout {

CheshireKat
źródło
1
Ahh! więc to jest to ...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
źródło
5

Jest szybka wersja:

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 (wersja 7.3.1) nie proponuje tych metod w autouzupełnianiu!

Jeśli potrzebujesz tylko nagłówka, po prostu zachowaj metodę header.

Kevin ABRIOUX
źródło
3
    @objc (collectionView:viewForSupplementaryElementOfKind:atIndexPath:)
    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { }

Powyższy kod zadziałał dla mnie

Bibin Jaimon
źródło
2

Mój problem polegał na tym, że w swift 3 nazwa funkcji viewForSupplementaryElementOfKind zmieniła się nieznacznie w stosunku do wszystkich postów, które były przepełnione. Dlatego nigdy nie było wywoływane. Upewnij się, że jeśli jesteś w Swift 3, jesteś dopasowany do funkcji delegowanej:

func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {}
Daniel Jones
źródło
Moje też. U mnie brakowało „_”, „atIndexPath” zamiast „at” i „NSIndexPath” zamiast „IndexPath”; skądś skopiowałem metodę i IDE nie dało mi błędu.
Ashkan Sarlak
1

Mam ten sam problem. Dodałem, referenceSizeForFooterInSectionale potem też viewForSupplementaryElementOfKindnie otrzymałem wezwania. Dodałem ten kod w viewDidLoad()i zadziałał:

if let flowLayout = self.collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
    flowLayout.sectionFootersPinToVisibleBounds = true   
}
Migotanie
źródło
0

Dla mnie w Swift 4.2 func collectionView (collectionView: kind: indexPath :) -> UICollectionReusableView nigdy nie była wywoływana. To było dla widoku kolekcji w UIViewController. Zauważyłem, że istniejące funkcje widoku kolekcji zostały zakwalifikowane za pomocą @objc i że UICollectionView nie przyjął protokołów UICollectionViewDataSource i UICollectionViewDelegate. Jak tylko zaadoptowałem protokoły, otrzymałem błąd, że funkcje widoku kolekcji nie pasują do protokołu. Poprawiłem składnię funkcji, usunąłem kwalifikatory i nagłówki sekcji zaczęły działać.

kod trishcode
źródło
0

Jeśli masz podklasę ogólną, musisz zadbać o określenie nazwy metody delegata ObjC, jeśli jest inna niż nazwa Swift ( https://bugs.swift.org/browse/SR-2817 ).

@objc (collectionView:viewForSupplementaryElementOfKind:atIndexPath:)
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
...
Adrian Bilescu
źródło