UICollectionView的cellForItemAtIndexPath没有被调用


104

只有第二次使用UICollectionView了,也许我咬的东西比我可以咀嚼的要多,但是:

我正在实现一个UICollectionView(myCollectionView),它使用已子类化的自定义UICollectionViewCell。子类化的单元格(FullReceiptCell)包含UITableView,并且是viewcontroller的大小。我试图允许FullReceiptCells之间的水平滚动。

包含myCollectionView的子类UICollectionViewController被推入导航控制器堆栈。当前,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

Answers:


135

对于后来在这里绊倒的人....原因:

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

之所以没有被调用,是因为collectionViewFlowLayout高度的itemSize太大。

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

如果将高度更改为410,它将执行cellForItemAtIndexPath。


您能否详细说明一下。对我来说,情况也是一样
user1010819 2013年

我刚刚发现,您也需要注意collectionViewContentSize
Dimitar Marinov

49
如果您使用自动布局-请确保在collectionView上设置高度限制-这样做浪费了很多时间!
bpn

因为创纪录的高度限制对我没有用。水平中心限制成功了
Mohamed Emad Hegab 2014年

4
如果您的collectionView被AutoLayout限制为topLayoutGuide,并且不应在NavigationBar下滚动,请确保Adjust Scroll View Insets在Storyboard上取消选中 ViewController。
布鲁诺·加里纳里'16


31

如果不向集合视图提供内容大小信息,则不会调用cellForItemAtIndexPath。

  1. 如果使用的是Flow版式:您需要正确设置项目大小。
  2. 如果您从UICollectionViewLayout继承了一个自定义布局,请执行以下操作:确保从collectionViewContentSize方法返回适当的大小。

对于后者,您还将观察到您的layoutAttributesForElementsRect也没有被调用。原因是您尚未指定内容大小,默认情况下大小为CGSizeZero。这基本上告诉收藏夹视图您没有要绘画的内容,因此它不会打扰您询问属性或单元格。

因此,只需覆盖collectionViewContentSize并在那里提供适当的大小,它就可以解决您的问题。


1
例如,要使用全部可用大小,请从collectionViewContentSize返回collectionView.frame.size(而不是默认为0、0的collectionView.contentSize)
Adam Loving

谢谢!这个答案帮助我b / c我有一个自定义的UICollectionViewLayout。如果我以横向模式在模拟器中启动该应用程序,则某些单元格不会出现在初始视图中。覆盖内容大小对我来说解决了这个问题。
克里斯·利夫达尔

1
谢谢。在我的情况下,collectionViewContentSize宽度错误地返回0,这就是cellForItemAtIndexPath未调用的原因。
izerik

16

也许我只是忽略了它,但是看起来您缺少委托和数据源。确保在头文件中添加了以下内容:

<UICollectionViewDelegate, UICollectionViewDataSource>

并在您的viewDidLoad方法中添加以下内容:

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

另外,如果要通过.xib加载它,请确保已将IBOutlet连接到UICollectionView。


1
我没有显示它,但是我已经在头文件中注明了委托和数据源。此外,我已将IBOutlet连接到myCollectionView。此collectionview的委托和数据源已设置为FullReceiptViewController。奇怪的是,numberOfItemsInSection(数据源协议方法)正在被调用并返回大于0的整数
。– IkegawaTaro

嗯,启动应用程序时,“收藏夹”视图会显示还是执行任何操作?这听起来像它确实有它的一些项目,如果numberOfItemsInSection返回的东西大于0
安东尼卡斯泰利

感谢您的跟进。collectionview确实显示了...我知道了,因为我更改了背景色。我相信我已经找到了问题:[self.myCollectionViewFlowLayout setItemSize:CGSizeMake(320,548)]; 太大了 如果将高度降低到410,则可以调用cellForItemAtIndexPath方法。
IkegawaTaro

@AnthonyCastelli您好,我也遇到了同样的问题,在弹出的viewController上调用了numberOfItemsInSection,但在cellForItemsAtIndexPath上没有调用。那么你有线索吗?
Bhavin Kansagara

16

对于更复杂的视图层次结构,请查看此博客。它救了我的命!

self.automaticallyAdjustsScrollViewInsets = NO;

1
我花了很多时间在这上-一切都归结于此。如果使用情节提要或XIB,请查看父视图控制器,然后在默认情况下启用的“属性”检查器中取消选择“调整滚动视图插图”。我尝试了所有其他答案,但它们没有起作用,这归结于此。
etayluz '16

15

如果您的类是UICollectionviewController的子类,并且您正在以编程方式创建collectionView,则使用

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

    collectionView?.setCollectionViewLayout(layout, animated: false)

这就是答案解决了我的问题!覆盖方法func collectionView(_ collectionView:UICollectionView,布局collectionViewLayout:UICollectionViewLayout,sizeForItemAt indexPath:IndexPath)-> CGSize {<#code#>}对我不起作用。
迈克,

8

我正在使用自动布局,在我的情况下缺少高度限制


6

我的问题是我在同一视图中有2个集合视图,并且两个都共享一个计算UICollectionViewFlowLayout实例。一旦创建了相同流程布局的单独实例,它就可以正常工作。


5

就我而言,我非常愚蠢地忘记要做的是实现UICollectionViewDataSourceprotocol方法numberOfItemsInSection,这是另一件事需要检查。


4

另外,请确保在使用动画更新集合视图(插入,删除,更新或performBatchUpdates)时未调用reloadData。


4

就我而言,set collectionView.prefetchingEnabled = NO;解决了我的问题。仅适用于iOS 10。


2
不久前,我对这个答案进行了投票,今天,它再次帮助了我:D对于这个答案,你应该得到一个贵族。再次感谢!
Maciek Czarnik

这个答案对我有用!我希望对为什么将其包含进来有一个解释,因为一开始我从未将其设置为true。
Lance Samaria

3

对于我来说,通过修复调用cellForItem方法的项目高度== 0时,发生了这种情况。


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

在情节提要/ xib UICollectionView属性中,cellSize不得为{0,0}



1

我也一样 我有2个UICollectionViews,并且由于不需要而删除了一次。之后,我意识到没有调用CellForItemAtIndexPath,而是调用了其他必需的方法。我尝试了以上所有方法,但随后进行了标准魔术。从情节提要中删除了集合视图,然后再次添加。然后它开始工作。不知道为什么,我没有任何解释,但也许有一些连接问题。


我从情节提要中的另一个UIViewController复制了UICollectionView。我删除了CollectionView并再次添加以使其起作用。谢谢您的回答。
Drunken Daddy

1

只是解决了这个问题,针对某种特定情况。

就我而言,我是在父ViewController中手动初始化UICollectionViewController,然后将UICollectionViewController的视图添加为子视图。

我通过在父视图的viewDidAppear中的collectionView上调用“ setNeedsLayout”和/或“ setNeedsDisplay”来解决此问题:

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

1

使用时,请UICollectionViewDelegateFlowLayout注意此函数返回的内容。双方widthheight应大于0。我用作window框架参考,但是由于复杂的视图层次结构窗口nil在运行时使用。如果需要根据屏幕宽度调整元素的宽度,请使用UIScreen.main.bounds

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

1

就我而言,我有collectionView一个UIStackViewalignment = .center。因此,collectionView没有宽度。设置为时stackView.alignment.fill一切都很好。


0

对我来说,我通过自动布局来更新self.view(collectionView的超级视图)的高度,然后必须调用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。我最终只是删除了包含的视图控制器,并在情节提要中重新创建了它,这似乎解决了这个问题。我的猜测是发生了某种情节提要板损坏。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.