Стільниця UICollectionViewForItemAtIndexPath не викликається


104

Тільки вдруге я використовую UICollectionView і, можливо, я відкусив більше, ніж можу жувати, але все-таки:

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

Підклас UICollectionViewController, який містить myCollectionView, пересувається на стек контролера nav. Наразі ввімкнено логотипи myCollectionView та горизонтальну прокрутку. Однак жодних комірок не видно. Я це підтвердив

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

запустив і повертає ціле число, що перевищує 0. Я також підтвердив, що делегат myCollectionView і джерело даних належним чином встановлені в ІБ на підкласи 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

Відповіді:


135

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

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

його не називали через те, що висота itemSize для collectionViewFlowLayout була занадто великою.

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

Якщо я зміню висоту на 410, вона виконає cellForItemAtIndexPath.


Чи можете ви детальніше розробити. Те саме відбувається і зі мною
користувач1010819

Я щойно виявив, що вам потрібно бути обережним і з collectionViewContentSize
Димитар Маринов

49
Якщо ви використовуєте автоматичний розклад, не забудьте встановити обмеження висоти на collectionView - витрачайте на це багато годин!
bpn

бо обмеження висоти рекорду не спрацювало для мене .. горизонтальні обмеження в центрі зробили трюк
Mohamed Emad Hegab

4
Якщо ваш collectionView обмежений для topLayoutGuide з AutoLayout, і він не повинен прокручуватися під NavigationBar, не забудьте зняти прапорець Adjust Scroll View Insetsу ViewController на Storyboard.
Бруно Галінарі

96

У моєму випадку це було тому, що мій клас компонування неправильно підкласифіковано UICollectionViewLayoutзамістьUICollectionViewFlowLayout


1
СПАСИБІ. Баггер, я витратив віки на це.
Рамбатіно

Це було і моє питання! Це трохи протизаконно, тому мені навіть не прийшло в голову. Дякую за це!
WendiKidd

Те саме для мене! його так просто не помітити! ще раз дякую
arvidurs

Facepalm тут, дякую, що ви вказали це (4 роки тому).
Міландер

Я стикався з тим же питанням. Спасибі
Піюш Гупта

31

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

  1. Якщо ви використовуєте макет потоку : Вам потрібно правильно встановити розміри елементів.
  2. Якщо у вас є підклас власного макета з UICollectionViewLayout : переконайтеся, що ви повертаєте потрібний розмір з методу collectionViewContentSize.

У разі останнього, ви також помітите, що ваш layoutAttributesForElementsRect також не викликається. Причина полягає в тому, що ви не вказали, який ваш розмір вмісту, і за замовчуванням розмір буде CGSizeZero. Це, по суті, говорить про те, що ви не маєте жодного вмісту для малювання, щоб не турбувати вас про атрибути чи комірки.

Отже, просто переосмислите collectionViewContentSize і введіть там належний розмір, це повинно вирішити вашу проблему.


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

Дякую! Ця відповідь допомогла мені, коли я маю власну UICollectionViewLayout. Якщо я запустив додаток в тренажері в альбомній орієнтації, деякі клітини не з’являлися в початковому вікні. Перебіг розміру вмісту вирішив для мене цю проблему.
Кріс Лівдал

1
Дякую. У моєму випадку collectionViewContentSizeнеправильно повернуто 0 для ширини, тому cellForItemAtIndexPathне було викликано.
izerik

16

Можливо, я просто його не помічаю, але, здається, у вас відсутній ваш делегат та джерело даних. У файлі заголовка переконайтесь, що ви додали:

<UICollectionViewDelegate, UICollectionViewDataSource>

і у вашому методі viewDidLoad додайте це:

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

Крім того, якщо ви завантажуєте його через .xib, переконайтеся, що ви підключили IBOutlet до UICollectionView.


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

Хм, коли ви запускаєте програму, чи відображається перегляд колекції чи щось робити? Здається, що в ньому є деякі елементи, якщо numberOfItemsInSection повертає щось більше, ніж 0.
Ентоні Кастеллі

Дякуємо за продовження роботи. Збірка перегляду показує ... Я можу сказати, тому що я змінив колір фону. Я вважаю, що я знайшов проблему: [self.myCollectionViewFlowLayout setItemSize: CGSizeMake (320, 548)]; Це було занадто велико. Якщо я зменшу висоту до 410, я можу отримати метод CellForItemAtIndexPath, який потрібно викликати.
IkegawaTaro

@AnthonyCastelli Здрастуйте, я також зіткнувся з тією ж проблемою, що номерOfItemsInSection викликається на поп-панелі для переглядуController, але не cellForItemsAtIndexPath. так ви зрозумієте?
Бхавін Кансагара

16

Для більш складного перегляду ієрархії, будь ласка, перевірте цей блог . Це врятувало мені життя!

self.automaticallyAdjustsScrollViewInsets = NO;

1
Я витратив на це стільки часу - і все зводилося до цього. Якщо ви використовуєте розкадровку або XIB, подивіться на батьківський контролер подання та зніміть прапорець "Налаштувати прокрутки для перегляду прокрутки" в інспекторі атрибутів, який увімкнено за замовчуванням. Я спробував всі інші відповіді, і вони не спрацювали, це дійшло до цього.
еталуз

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 не викликається, коли огляд колекції оновлюється анімацією (вставляти, видаляти, оновлювати чи виконуватиBatchUpdates).


4

У моєму випадку сет collectionView.prefetchingEnabled = NO;вирішив мою проблему. Працює лише на iOS 10.


2
Я відповів на цю відповідь деякий час тому, і сьогодні вона мені знову допомогла: D Ти заслуговуєш благородного на цю відповідь. Знову дякую!
Масьєк Царник

ця відповідь спрацювала на мене! Мені б хотілося, щоб було пояснення, чому він включений до нього, тому що я ніколи не ставив це до істини для початку.
Ленс Самарія

3

Для мене це відбувалося, коли висота елемента == 0, виправляючи метод CellForItem, викликався.


3

Десять хвилин тому я також зіткнувся з цією проблемою, я зробив дурну помилку.

Мій намір - використовувати UICollectionViewFlowLayout,

Але через помилки я використав UICollectionViewLayout.


3

У моєму випадку зміна напівпрозорої UINavigationBar на NO вирішила проблему.


3

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

  • Видаліть макет потоку в ІБ
  • Складіть / запустіть додаток
  • Поверніть макет потоку назад

Зараз це працювало :)


2

Переконайтеся, що також numberOfSectionsInCollectionViewповертається додатне ціле число.

У колекції має бути принаймні один розділ.


2

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


2

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

collectionView.translatesAutoresizingMaskIntoConstraints = false

2

Це можуть бути пов'язані з проблемами розташування. Перевірте попередження макета з консолі, якщо вони існують.


2

У моєму випадку подання колекції не було повністю видимим у його батьківському поданні через неправильні обмеження автоматичного компонування. Таким чином, виправлення обмежень зробило вигляд колекції всім видимим і виклик cellForItemAtIndexPath.


2

У раскадровці / xib властивості UICollectionView властивість cellSize НЕ МОЖЕ бути {0, 0}


2

Якщо ви використовуєте протоколи перегляду колекції, ви повинні підключити CollectionViewDataSourceі CollectionViewDelegateпротоколи до свого ViewController. Розетки для інтерфейсу


1

Те саме сталося і зі мною. У мене було 2 UICollectionViews, і я був видалений один раз, оскільки мені цього не потрібно. Після цього я зрозумів, що CellForItemAtIndexPath не викликає, а інші необхідні методи. Я спробував усе вищесказане, але тоді я зробив стандартну магію. Вилучено подання колекції з табло та додано знову. Потім воно почало працювати. Не впевнений, чому я не маю пояснень, але, можливо, деякі проблеми з підключенням.


Я скопіював свій UICollectionView з іншого UIViewController в раскадровці. Я видалив CollectionView і знову додав, щоб він працював. Спасибі за вашу відповідь.
П’яний тато

1

Щойно вирішено це питання для дещо конкретної ситуації.

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

Я вирішив проблему, викликавши "setNeedsLayout" та / або "setNeedsDisplay" у collectionView у поданні батьківDidAppear:

- (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

У моєму випадку я мав collectionViewв a UIStackViewс alignment = .center. Так collectionViewширина не мала. При встановленні stackView.alignmentна .fillвсе все було добре.


0

Для мене я оновлюю висоту self.view (нагляд колекціїView) за допомогою автовідтворення, і ОБОВ'ЯЗКОВО зателефонувати 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)

0

У мене була подібна проблема. Але натомість cellForItemAtIndexPathназивали, коли кількість елементів була> 1, а не тоді, коли був лише один предмет. Я спробував багато запропонованих тут рішень і подібний до багатьох, я виявив, що це стосується розміру виробів. Для мене рішенням було змінити розмір кошторису UICollectionViewз " Автоматичний" на " Спеціальний" .

Встановити розмір кошторису на спеціальний


-1

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.