【问题标题】:cellForRowAtIndexPath doesn't get called after calling reloadData in UICollectionView在 UICollectionView 中调用 reloadData 后未调用 cellForRowAtIndexPath
【发布时间】:2015-05-07 14:29:35
【问题描述】:

我有一个UICollectionView,它使用UICollectionViewCell 的子类。最初,我的dataSource 包含 5 个项目,当用户向下滚动时,我获取更多数据并将它们添加到我的dataSource,然后我调用reloadData

但只有 3 个项目可见。当我向上滚动时,我看不到其余的项目,只是一个空白区域。我注意到 cellForRowAtIndexPath 只被调用这 3 个项目。

当我导航到我的父视图并返回到包含我的UICollectionView 的视图时,我可以看到所有项目。

注意:我已经实现了layout:sizeForItemAtIndexPath 函数,因为每个单元格都有不同的大小。

编辑:

我部分解决了这个问题。我有一个 refreshControl,我在后台线程中调用了 endRefreshing。

我正在添加图片以便更好地演示现在发生的事情:

  • 第一张图片是在获取新数据之前,您可以看到数据显示完美。

  • 第二张图片是在获取新数据之后,您可以看到新项目的高度与之前的项目(旧单元格)完全相同,并且有一个空白区域,当我向下滚动时,我可以看到其余部分数据,当我向上滚动时,顶部的单元格得到正确的高度,如第三张图片所示。

完成加载新项目后,我调用此方法

- (void)updateDataSource
{
   self.collectionViewDataSource = _manager.messages;
   [self.collectionView reloadData];
}

我检查了 numberOfItemsInSection 方法,它返回正确的项目数。

这是我的布局:sizeForItemAtIndexPath

- (CGSize)collectionView:(UICollectionView *)collectionView layout:   (UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:  (NSIndexPath *)indexPath 
{
// Here I am calculating the width and height of the textView which will fit the message

SPH_PARAM_List *feed_data=[[SPH_PARAM_List alloc]init];
feed_data=[self.collectionViewDataSource objectAtIndex:indexPath.row];

if ([feed_data.chat_media_type isEqualToString:kSTextByme]||[feed_data.chat_media_type isEqualToString:kSTextByOther])
{

    NSAttributedString *aString = [[NSAttributedString alloc] initWithString:feed_data.chat_message];

    UITextView *calculationView = [[UITextView alloc] init];
    [calculationView setAttributedText:aString];

    [calculationView setFont:[UIFont systemFontOfSize:14]];
    [calculationView setTextAlignment:NSTextAlignmentJustified];


    CGSize sc = [calculationView sizeThatFits:CGSizeMake(TWO_THIRDS_OF_PORTRAIT_WIDTH, CGFLOAT_MAX)];

    NSLog(@"IndexPath: %li Height: %f", (long)indexPath.row ,sc.height);

    return CGSizeMake(self.view.frame.size.width - (5 * 2), sc.height);

}

return CGSizeMake(self.view.frame.size.width - (5 * 2), 90);

}

编辑 2:

我注意到 layout:collectionViewLayoutsizeForItemAtIndexPath: 被调用并返回正确的高度,但 cellForItemAtIndexPath 仍然处理旧的。

【问题讨论】:

  • 不是cellForItemAtIndexPath的方法吗?
  • 用相关代码更新您的问题,以便我们指出问题。
  • @rmaddy 我已经更新了我的问题并添加了一些相关代码,你需要我添加更多吗?
  • 您是否尝试过使布局无效?由于顶部单元格需要重新加载和调整大小,您可能需要在数据更改时调用[collectionView.collectionViewLayout invalidateLayout];,因为重复使用的单元格必须重新确定高度
  • 只是一个建议:当我看到这样的问题时,它们通常是由于没有从主队列调用 UI Kit 引起的。确保在主队列上分派所有呼叫。 dispatch_async(dispatch_get_main_queue(), ^{ ... do stuff

标签: ios uicollectionview uicollectionviewcell


【解决方案1】:

您可能需要使布局无效,以便重新计算单元格位置和高度,因为简单地重新加载数据不会正确设置单元格高度(因为单元格被重复使用)。

- (void)updateDataSource
{
   self.collectionViewDataSource = _manager.messages;
   [self.collectionView reloadData];
   // Add this line.
   [self.collectionView.collectionViewLayout invalidateLayout];
}

【讨论】:

  • 很遗憾,没有任何改变。 :( 谢谢你的建议。
  • 我注意到 collectionView: layout:collectionViewLayout sizeForItemAtIndexPath: 被调用并返回一个新高度,但 cellForItemAtIndexPath 仍然处理旧高度。
  • 你不会改变布局吧?只是刷新细胞?如果在布局无效后重新加载部分(而不是整个数据集)会发生什么? [self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:0]]; ?
  • 改变布局是什么意思?我只是在我的数据源中添加新项目,但每个项目都有不同的高度。我试过了,没有任何改变。
  • 根据上面的图片,看起来新数据加载正常。问题似乎是布局没有正确更新 - 看起来非常类似于这个问题stackoverflow.com/questions/13750428/…
【解决方案2】:

在您显示代码之前无法弄清楚。但是,我猜您的数据源没有更新。只需检查一下,您的 DataSource 应该在 reloadData 之前获取数据。您可以放置​​一些日志来检查 reloadData 之前/之后的项目数。这可能会有所帮助。

【讨论】:

  • 我检查了我的数据源,它已更新。我添加了一些相关代码。
  • 尝试 performBatchUpdates 而不是简单地替换完整列表,它会使布局无效。这可能会有所帮助。 if (//要添加的更多项目) { [self.collectionView performBatchUpdates:^{//将项目添加到集合视图}]; }else { [self.collectionView reloadData]; }
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多