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?


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.


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.


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


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 {


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

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.


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

Powyższy kod zadziałał dla mnie


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 {}

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   
}

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ć.


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 {
...
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.