Метод UICollectionReusableView не вызывается


79

Я хочу, чтобы в моих разделах UICollectionViewбыл заголовок с изображением.

Я выполнил следующие шаги:

  • в раскадровке, назначил заголовок как аксессуар для моего UICollectionView
  • дал ему идентификатор
  • создал подкласс UICollectionReusableViewдля него
  • назначил настраиваемый класс классу в раскадровке.
  • поставить ImageViewна заголовок аксессуар
  • сделал выход для ImageViewпользовательского класса в .hфайле
  • Реализовано на 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;
}

Я знаю, что методы источника данных и делегата работают, потому что я могу видеть все ячейки и их разделы. Однако у меня нет заголовков. Я установил точку останова в методе выше, и он никогда не вызывается.

Что я делаю неправильно?


3
Обратите внимание, что вы сравниваете указатели строк kind == UICollectionElementKindSectionHeaderвместо содержимого строк, которое вы, вероятно, захотите использовать [kind isEqualToString: UICollectionElementKindSectionHeader]вместо этого.
Mac_Cain 13

Ответы:


200

Похоже, вы должны указать свой заголовок ненулевого размера или collectionView:viewForSupplementaryElementOfKind:atIndexPathон не вызывается. Поэтому либо установите headerReferenceSizeсвойство макета потока следующим образом:

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

Swift 5+

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

или реализуйте, collectionView:layout:referenceSizeForHeaderInSectionесли вы хотите варьировать размер по разделам.


1
в представлении коллекции, могу ли я сделать динамическую высоту с помощью автоматического раскладки вместо определения размера headerReference?
Khant Thu Linn

Можно ли установить headerReferenceSize в Storyboard на flowLayout?
Радек Вильчак

1
Да, это сработало! layout.headerReferenceSize = CGSize (ширина: (self.collectionView? .frame.width) !, высота: 50); для swift4
Antony Ouseph 04

headerReferenceSizeработает, но мне нужны разные размеры для разных разделов. А указанный вами метод вообще не вызывается
Вячеслав Герчиков

33

Вы ответили на вопрос, но на словах я понимаю лучше:

Чтобы вызвать вызываемый метод, добавьте следующие методы:

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

... и идти оттуда.


31

Swift 4 Xcode 9.1 Бета 2

Добавить @objc

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

Кредиты: https://medium.com/@zonble/your-delegation-methods-might-not-be-called-in-swift-3-c6065ed7b4cd


Спасибо! Спас мою задницу. Кстати, я заметил, что эта функция не отображается в списке автозаполнения для collectionViewDelegate. Не знаю почему, так странно. Также странно, что нам нужен тег @objc перед ним.
C0D3

3
У меня сработало только добавление @objc к функции в Swift 4. Смешной.
Луи Кремен

7
Соответствие UICollectionViewDelegateFlowLayout вместо UICollectionViewDelegate также исправляет это без @objc, если вы используете UICollectionViewFlowLayout.
nemissm

Намного лучше, если вы используете границы collectionView для установки значения с вашего верхнего / нижнего колонтитула раздела: let size = CGSize (collectionView.bounds.width, height: 50)
omaestra

18

Вы добавили UICollectionViewDelegateFlowLayout в текущий интерфейс? Это сработало для меня.

@interface MyViewController () <UICollectionViewDelegateFlowLayout>

Swift:

class MyViewController: UICollectionViewDelegateFlowLayout {


1
Ах! так вот оно ...UICollectionViewDelegateFlowLayout
Аян Сенгупта

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

Есть быстрая версия:

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 (версия 7.3.1) не предлагает эти методы в автозаполнении!

Если вам просто нужен заголовок, просто сохраните метод заголовка.


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

Приведенный выше код работал у меня


2

Моя проблема заключалась в том, что в Swift 3 имя функции viewForSupplementaryElementOfKind немного изменилось по сравнению с любыми сообщениями, которые были при переполнении стека. Следовательно, его никогда не называли. Убедитесь, что, если вы используете Swift 3, функция делегата совпадает:

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

Мой тоже. Для меня отсутствовал «_», «atIndexPath» вместо «at» и «NSIndexPath» вместо «IndexPath»; поскольку я скопировал метод откуда-то, и IDE не выдала мне ошибку.
Ашкан Сарлак

1

У меня такая же проблема. Я добавил, referenceSizeForFooterInSectionно потом мне viewForSupplementaryElementOfKindне позвонили. Я добавил этот код, viewDidLoad()и он сработал для меня:

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

0

Для меня в Swift 4.2 функция func collectionView (collectionView: kind: indexPath :) -> UICollectionReusableView никогда не вызывалась. Это было для представления коллекции в UIViewController. Я заметил, что существующие функции просмотра коллекции были квалифицированы с помощью @objc, и что UICollectionView не принял протоколы UICollectionViewDataSource и UICollectionViewDelegate. Как только я принял протоколы, у меня возникли ошибки, что функции представления коллекции не соответствуют протоколу. Я исправил синтаксис функции, удалил квалификаторы, и заголовки разделов заработали.


0

Если у вас есть общий подкласс, вы должны указать имя метода делегата ObjC, если оно отличается от имени Swift ( https://bugs.swift.org/browse/SR-2817 ).

@objc (collectionView:viewForSupplementaryElementOfKind:atIndexPath:)
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
...
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.