CellForItemAtIndexPath UICollectionView не вызывается


104

Только второй раз использую UICollectionView, и, возможно, я откусил больше, чем могу прожевать, но тем не менее:

Я реализую UICollectionView (myCollectionView), который использует пользовательский UICollectionViewCell, который я подклассифицировал. Подклассы ячеек (FullReceiptCell) содержат UITableView и имеют размер контроллера представления. Я пытаюсь разрешить горизонтальную прокрутку между FullReceiptCells.

Подкласс UICollectionViewController, содержащий myCollectionView, помещается в стек контроллера навигации. В настоящее время включены функции myCollectionView и горизонтальная прокрутка. Однако ячеек не видно. Я подтвердил это

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section

выполняется и возвращает целое число больше 0. Я также подтвердил, что делегат myCollectionView и источник данных правильно установлены в IB для подкласса UICollectionViewController.

Метод загрузки ячеек:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath

не называется.

Здесь я нажимаю UICollectionViewController и свой метод viewDidLoad внутри этого контроллера (ПРИМЕЧАНИЕ: initWithBill является переопределением обычного инициализатора):

В предыдущем файле ViewControllers .m:

FullReceiptViewController *test = [[FullReceiptViewController alloc] initWithBill:currentBill];
test.title = @"Review";
[self.navigationController pushViewController:test animated:YES];

В FullReceiptViewController.m:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    [self.myCollectionView registerClass:[FullReceiptCell class] forCellWithReuseIdentifier:@"FullReceiptCellIdentifier"];
    self.myCollectionView.pagingEnabled = YES;
    // Setup flowlayout

    self.myCollectionViewFlowLayout = [[UICollectionViewFlowLayout alloc] init];
    [self.myCollectionViewFlowLayout setItemSize:CGSizeMake(320, 548)];
    [self.myCollectionViewFlowLayout setSectionInset:UIEdgeInsetsMake(0, 0, 0, 0)];
    [self.myCollectionViewFlowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
    self.myCollectionViewFlowLayout.minimumLineSpacing = 0;
    self.myCollectionViewFlowLayout.minimumInteritemSpacing = 0;
    [self.myCollectionView setCollectionViewLayout:myCollectionViewFlowLayout];
    //testing to see if the collection view is loading
    self.myCollectionView.backgroundColor = [UIColor colorWithWhite:0.25f alpha:1.0f];

Есть какие-нибудь подсказки относительно того, почему его не называют?


Я использую XIB. Я не могу удалить что-либо в cellForItemsAtIndexPath, потому что он никогда не вызывается.
IkegawaTaro 03

Ответы:


135

Для тех, кто тут споткнется позже .... причина:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath

не был вызван из-за слишком большой высоты itemSize для коллекцииViewFlowLayout.

[self.myCollectionViewFlowLayout setItemSize:CGSizeMake(320, 548)];

Если я изменю высоту на 410, он выполнит cellForItemAtIndexPath.


Не могли бы вы уточнить немного подробнее. То же самое происходит и со мной
user1010819

Я только что обнаружил, что с collectionViewContentSize тоже нужно быть осторожным
Димитар Маринов

49
Если вы используете автоматическое размещение - обязательно установите ограничение по высоте для collectionView - потрачено на это много часов!
bpn

ограничение по высоте не сработало для меня .. ограничение по горизонтали в центре
помогло

4
Если ваш collectionView ограничен topLayoutGuide с помощью AutoLayout и не должен прокручиваться в NavigationBar, не забудьте снять флажок Adjust Scroll View InsetsViewController в Storyboard.
Бруно Галинари

96

В моем случае это произошло из-за того, что мой класс макета некорректно подклассифицирован UICollectionViewLayoutвместоUICollectionViewFlowLayout


1
СПАСИБО. Убей меня, я потратил на это целую вечность.
Рамбатино

Это тоже была моя проблема! Это немного нелогично, поэтому мне даже в голову не пришло. Спасибо за это!
WendiKidd

Мне то же! это так легко не заметить! еще раз спасибо
arvidurs 06

Facepalm, спасибо, что указали на это (4 года назад).
Миландер

Я столкнулся с той же проблемой. Спасибо
Пиюш Гупта

31

CellForItemAtIndexPath не будет вызываться, если вы не предоставите информацию о размере содержимого в представление коллекции.

  1. Если вы используете макет Flow : вам необходимо правильно установить размеры элементов.
  2. Если у вас есть собственный макет, созданный на основе UICollectionViewLayout : убедитесь, что вы возвращаете правильный размер из метода collectionViewContentSize.

В случае последнего вы также заметите, что ваш layoutAttributesForElementsRect также не вызывается. Причина в том, что вы не указали размер вашего контента, и по умолчанию размер будет CGSizeZero. Это в основном сообщает представлению коллекции о том, что у вас нет контента для рисования, поэтому он не беспокоит вас об атрибутах или ячейках.

Итак, просто переопределите collectionViewContentSize и укажите там правильный размер, это должно решить вашу проблему.


1
Например, чтобы использовать полный доступный размер, верните collectionView.frame.size из collectionViewContentSize (а не просто collectionView.contentSize, который по умолчанию равен 0, 0)
Adam Loving

Спасибо! Этот ответ помог мне, потому что у меня есть собственный UICollectionViewLayout. Если я запустил приложение в симуляторе в альбомной ориентации, некоторые ячейки не отображались в исходном виде. Переопределение размера содержимого устранило эту проблему для меня.
Крис Ливдал

1
Спасибо. В моем случае collectionViewContentSizeдля ширины было неправильно возвращено 0, поэтому функция cellForItemAtIndexPathне вызывалась.
изерик

16

Может, я просто не замечаю этого, но похоже, что вам не хватает делегата и источника данных. Убедитесь, что вы добавили в заголовочный файл:

<UICollectionViewDelegate, UICollectionViewDataSource>

и в вашем методе viewDidLoad добавьте это:

self.myCollectionView.delegate = self;
self.myCollectionView.dataSource = self;

Кроме того, если вы загружаете его через .xib, убедитесь, что вы подключили IBOutlet к UICollectionView.


1
Я не показывал это, но у меня уже есть делегат и источник данных, указанные в файле заголовка. Кроме того, я подключил IBOutlet к myCollectionView. Делегат и источник данных для этого представления коллекции были установлены на FullReceiptViewController. Странно то, что numberOfItemsInSection (метод протокола источника данных) вызывается и возвращает целое число больше 0.
IkegawaTaro

Хм, при запуске приложения вид Коллекции показывает или что-то делает? Похоже, что в нем есть какие-то элементы, если numberOfItemsInSection возвращает значение больше 0.
Энтони Кастелли

Спасибо за продолжение. Вид коллекции действительно показывает ... Я могу сказать, потому что я изменил цвет фона. Я считаю, что нашел проблему: [self.myCollectionViewFlowLayout setItemSize: CGSizeMake (320, 548)]; Это было слишком большим. Если я уменьшу высоту до 410, я могу вызвать метод cellForItemAtIndexPath.
IkegawaTaro

@AnthonyCastelli Привет, я тоже столкнулся с той же проблемой, numberOfItemsInSection вызывается при pop to viewController, но не cellForItemsAtIndexPath. так ты понял?
Bhavin Kansagara

16

Для более сложной иерархии представлений, пожалуйста, посетите этот блог . Это спасло мне жизнь!

self.automaticallyAdjustsScrollViewInsets = NO;

1
Я потратил на это столько времени - и все свелось к этому. При использовании раскадровки или XIB посмотрите на родительский контроллер представления и снимите флажок «Настроить вставки прокрутки представления» в инспекторе атрибутов, который включен по умолчанию. Я попробовал все остальные ответы, и они не сработали, все сводилось к следующему.
etayluz

15

Если ваш класс является подклассом UICollectionviewController и вы создаете collectionView программно, используйте

let layout = UICollectionViewFlowLayout()
    layout.scrollDirection = .Vertical
    layout.itemSize = CGSizeMake(50, 50)

    collectionView?.setCollectionViewLayout(layout, animated: false)

Это ответ решил мою проблему! Метод переопределения func collectionView (_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {<# code #>} у меня не работает.
Майк

8

Я использовал автоматическую раскладку, и в моем случае ограничение высоты отсутствовало


6

Моя проблема заключалась в том, что у меня было 2 представления коллекций в одном представлении, и оба использовали вычисляемый UICollectionViewFlowLayoutэкземпляр. Как только я создал отдельные экземпляры одного и того же макета потока, все заработало.


5

В моем случае я очень глупо забыл реализовать UICollectionViewDataSourceметод протокола numberOfItemsInSection, так что это еще одна вещь, которую нужно проверить.


4

Кроме того, убедитесь, что reloadData не вызывается во время обновления представления коллекции с помощью анимации (вставка, удаление, обновление или performBatchUpdates).


4

В моем случае набор collectionView.prefetchingEnabled = NO;решил мою проблему. Работает только на iOS 10.


2
Некоторое время назад я поддержал этот ответ, и сегодня он снова помог мне: D Вы заслуживаете Благородного за этот ответ, человек. Еще раз спасибо!
Maciek Czarnik

этот ответ сработал для меня! Я хотел бы, чтобы было объяснение того, почему он включен, потому что я никогда не устанавливал его в true с самого начала.
Лэнс Самария,

3

Это происходило для меня, когда высота элемента == 0, исправляя этот метод cellForItem, был вызван.


3

Десять минут назад я тоже столкнулся с этой проблемой, сделал глупую ошибку.

Я намерен использовать UICollectionViewFlowLayout,

Но из-за ошибок я использовал UICollectionViewLayout.


3

В моем случае изменение полупрозрачности UINavigationBar на NO решило проблему.


3

В Xcode 7.0.1 мы столкнулись с этой проблемой, когда скопировали раскадровку и сопутствующий код из другого проекта. Представление коллекции имело настраиваемый макет потока, установленный в раскадровке. Решение было:

  • Удалите схему потока в IB
  • Скомпилируйте / запустите приложение
  • Вернуть макет потока назад

Теперь заработало :)


2

Убедитесь, что также numberOfSectionsInCollectionViewвозвращает положительное целое число.

В коллекции должен быть хотя бы один раздел.


2

Убедитесь, что - (NSInteger) collectionView: numberOfItemsInSection: возвращает положительное (прочитанное, больше нуля) значение. Это может быть вопрос размещения [self.collectionView reloadData]; в обработчике завершения.


2

Я забыл установить для маски автоматического изменения размера значение false в представлении коллекции:

collectionView.translatesAutoresizingMaskIntoConstraints = false

2

Это могут быть проблемы с версткой. Проверьте предупреждения о макете с консоли, если они есть.


2

В моем случае представление коллекции не было полностью видно в родительском представлении из-за неправильных ограничений автоматического макета. Таким образом, исправление ограничений сделало представление коллекции полностью видимым, и был вызван cellForItemAtIndexPath.



2

Если вы используете вид сбора протоколов необходимо подключить CollectionViewDataSourceи CollectionViewDelegateпротоколы к вашему ViewController. Выходы построителя интерфейсов


1

То же случилось и со мной. У меня было 2 UICollectionView, и я удалил один раз, так как мне это не нужно. После этого я понял, что вызывается не CellForItemAtIndexPath, а другие необходимые методы. Я пробовал все вышеперечисленное, но потом проделал стандартную магию. Удалено представление коллекции из раскадровки и добавлено снова. Потом заработало. Не знаю, почему, и у меня нет объяснений, но, возможно, некоторые проблемы с подключением.


Я скопировал свой UICollectionView из другого UIViewController в раскадровку. Я удалил CollectionView и снова добавил, чтобы он работал. Спасибо за ваш ответ.
Drunken Daddy

1

Только что решил эту проблему для определенной ситуации.

В моем случае я вручную инициализировал UICollectionViewController в родительском ViewController, а затем добавлял представление UICollectionViewController в качестве подпредставления.

Я решил проблему, вызвав setNeedsLayout и / или setNeedsDisplay в collectionView в родительском viewDidAppear:

- (void)viewDidAppear:(BOOL)animated {
   [super viewDidAppear:animated];
   [_collection.view setNeedsLayout];
   [_collection.view setNeedsDisplay];
}

1

При использовании UICollectionViewDelegateFlowLayoutбудьте осторожны с тем, что возвращает эта функция. Оба widthи heightдолжны быть больше, чем 0. Я использовал windowкак ссылку на кадр, но из-за сложной иерархии представлений окно находилось nilво время выполнения. Если вам нужно настроить ширину элемента в зависимости от ширины экрана UIScreen.main.bounds.

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: 
           UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {}

1

У меня была аналогичная проблема. Но вместо этого cellForItemAtIndexPathбыл вызван, когда количество элементов было> 1, а не когда был только один элемент. Я пробовал многие из предложенных здесь решений и, как и многие, обнаружил, что это связано с размером элемента. Для меня решением было изменить размер оценки UICollectionViewс Автоматического на Пользовательский .

Установите размер оценки на Пользовательский


У меня была точно такая же проблема, спасибо!
Николай Денисюк

1

В моем случае у меня был collectionViewфайл UIStackViewс alignment = .center. Значит, у них collectionViewне было ширины. При выставлении stackView.alignmentна .fillвсе было хорошо.


0

Для меня я обновляю высоту self.view (супервизора collectionView) через autolayout и ДОЛЖЕН вызывать layoutIfNeededпосле этого.

[self.view mas_updateConstraints:^(MASConstraintMaker *make) {
    make.height.equalTo(@(height));
}];
[self.view layoutIfNeeded];

0

В моем случае мне пришлось настроить предполагаемый размер содержимого. размер содержимого не делал этого.

  let layout = collectionVC.collectionView.collectionViewLayout as! UICollectionViewFlowLayout
    layout.itemSize = CGSize(width: 100, height: 100)
    layout.estimatedItemSize = CGSize(width: 100, height: 100)

-1

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.