Метод 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если вы хотите варьировать размер по разделам.

Rdelmar
источник
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

Cwilliamsz
источник
Спасибо! Спас мою задницу. Кстати, я заметил, что эта функция не отображается в списке автозаполнения для 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 {

CheshireKat
источник
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)
}
Zeeshan
источник
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 {
...
Адриан Билеску
источник