【问题标题】:UICollectionView's cell disappearingUICollectionView 的单元格消失
【发布时间】:2012-11-01 21:29:40
【问题描述】:

发生了什么

目前我有一个在UITableView 中使用两个UICollectionViews 的应用程序。通过这种方式,我创建了一个看起来像 Pulse News 的应用程序。我的问题是,有时第 6 行和第 11 行会完全消失,在应该是单元格的地方留下一个空白区域。我实际上并不介意,如果所有的细胞都是这样的(这样我可以假设我没有正确地做事),但问题是,只是发生在那些特定的细胞上。

我的理论

第 6 行和第 11 行是我开始滚动时出现的行,因此默认情况下我可以看到 5 个单元格,当我进行第一次水平滚动时,第 6 行出现(有时是空白)。

我有什么

我现在唯一要做的就是:

 [self.collectionView registerNib:[UINib nibWithNibName:CELL_NIB_NAME bundle:nil] forCellWithReuseIdentifier:CELL_IDENTIFIER];

viewDidLoad。关于单元格的创建:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    MyCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CELL_IDENTIFIER forIndexPath:indexPath];

    NSMutableDictionary *dictionary = [self.DataSource objectAtIndex:[indexPath row]];

    [cell buildViewWithDictionary:dictionary withReferenceParent:self.referenceViewController];

    return cell;
}

因此,据我所知,这里没有什么好玩的。我虽然数据源(一个虚拟的 JSON 文件)有问题,但有时它可以正常工作并且单元格显示,所以我猜从那部分是可以的。

所以我的“问题”:有人知道发生了什么吗?我真的不想说这是 iOS 的错误,但我想不出别的。


编辑 1.0

神奇的是这个方法

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

在不计算 [0,5] 的情况下从 indexPath [0,4] 变为 [0,6]。我第一次在 iOS 中真正看到这种情况。


编辑 2.0

我已经切换了创建单元格的方式,而不是出队,我使用的是旧方式:

NSArray *nib = [[NSBundle mainBundle] loadNibNamed:CELL_NIB_NAME owner:self options:nil];
MyCell *cell = (MyCell *)[nib objectAtIndex:0];

还是一样的悲惨结果。

【问题讨论】:

  • 我遇到了同样的问题,但是消失的单元格最终会呈现在前一个单元格的下方!很奇怪。我认为这是 iOS 中的错误。
  • 奇怪的事情正在发生。 =/ 但仍然是一个出色的控制器..
  • 我有使用集合视图创建的经典网格视图。我连续有 3 个单元格有小间隙。同样的事情也发生在这里,但似乎非常随机。有时,一个单元格会连续排在第 4 位,而在预期的位置上什么都没有。

标签: ios xcode uicollectionview uicollectionviewcell


【解决方案1】:

在我的情况下,导致单元格消失的原因是数据源被过早地释放。 UICollectionView.dataSource 是一个弱属性,这意味着除非您保持对它的强引用,否则该对象将在您创建的范围结束时被释放。当我点击UICollectionView 时,问题就表现为细胞消失。

【讨论】:

    【解决方案2】:

    在我的情况下,单元格消失的问题是由于 IQKeyboardManager SDK 添加到项目中。 因为这个SDK在整个项目中触发了键盘动画,即使你不直接将它添加到单独的文件中。

    对我来说奇怪的是,仅当您为集合视图添加 UIEdgeInset 时才会出现问题,在我的情况下,该值高于 .bottom 的 40。

    如何解决?你需要解锁 pod 文件并添加

    DispatchQueue.main.async {}
    

    对于这个动画。 如果是 UICollectionViewController 它的内部

    @objc internal func keyboardWillHide(_ notification: Notification?) {}
    

    线法

     if let lastScrollView = lastScrollView {}
    

    当你为这个动画添加主队列时,问题就消失了。

    【讨论】:

      【解决方案3】:

      刚刚遇到了所有 UICollectionView 单元格在滚动时消失的问题。

      这是因为我已经声明了

      extension UICollectionViewLayout {
          static let defaultLayout: UICollectionViewLayout {
              let layout = UICollectionViewFlowLayout()
              layout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
              return layout
          }()
      }
      

      ... 表示在多个 UICollectionView 中使用了相同的布局实例。我本来打算把它变成一个计算变量。希望这对不小心在多个集合视图中使用相同布局对象的人有所帮助。

      【讨论】:

        【解决方案4】:

        当我突然遇到同样的问题并花了一些时间找出滚动过程中单元格消失的可能原因之一时,我也会添加我的答案。

        问题的先决条件:

        1. 你有一个UICollectionView 实例
        2. 你有一个UICollectionViewFlowLayoutSubclass

        问题

        滚动到特定点后,单元格从集合视图中消失。

        问题的根源在于 UICollectionViewFlowLayout 的错误子类化。

        正如它在documentation 中明确指出的那样:

        每个布局对象都应该实现以下方法:

        - collectionViewContentSize
        - layoutAttributesForElements(in:)
        - layoutAttributesForItem(at:)
        - layoutAttributesForSupplementaryView(ofKind:at:) // (if your layout supports -supplementary views)
        -layoutAttributesForDecorationView(ofKind:at:) // (if your layout supports decoration views)
        - shouldInvalidateLayout(forBoundsChange:)
        

        通过依赖UICollectionViewFlowLayout 实现上述方法,我们忽略了一个事实,即func layoutAttributesForElements(in rect: CGRect)collectionViewContentSize 将生成错误的contentSize(如果所有单元格都具有正确的大小itemSize 的大小和内容的大小是对应的。只要滚动offsetY 大于contentSize 高度单元格就会全部消失。

        解决办法

        解决方案是正确的UICollectionViewFlowLayout 子类化。覆盖所有required to override 的方法,一切都会正常工作。

        【讨论】:

          【解决方案5】:

          我们最近遇到了消失的单元格,发现我们不小心插入了 0x0 大小的单元格,而不是跳过“隐藏”的单元格。由此产生的行为非常令人困惑,并不表明这些不可见的细胞是问题所在。我们会看到大小正确的单元格和布局,但一些有效的单元格会在屏幕滚动后始终消失。我不知道为什么混合 0 大小的单元格会导致这种行为,但删除它们可以解决问题。这可能不会导致您的问题,但这可能有助于开发人员搜索类似症状。

          【讨论】:

            【解决方案6】:

            我认为这不是 UICollectionView 的错误,可能是您在 - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect 方法中没有返回正确的数据。

            你可以看这个demo:https://github.com/lqcjdx/YLTagsChooser,所有的单元格都可以在滑动UICollectionView时出现。

            【讨论】:

              【解决方案7】:

              对我来说,这个问题似乎与我让我的 collectionview 适应打开的键盘以防止内容重叠的方式有关。

              在我的观察者中回应 KeyboardWillShow 我有这个:

              var userInfo = obj.UserInfo[UIKeyboard.FrameEndUserInfoKey];
              if (userInfo is NSValue value)
              {
                  var rect = value.CGRectValue;
                  var windowOffset = this.Superview.ConvertPointToView(this.Frame.Location, UIApplication.SharedApplication.KeyWindow);
                  var newHeight = rect.Y - windowOffset.Y;
              
                  this._controller.CollectionView.Frame = new CGRect(0, 0, this._controller.CollectionView.Frame.Width, newHeight);
              }
              

              改成这样后:

              var userInfo = obj.UserInfo[UIKeyboard.FrameBeginUserInfoKey];
              if (userInfo is NSValue value)
              {
                  var rect = value.CGRectValue;
                  UIEdgeInsets contentInsets = new UIEdgeInsets(0, 0, rect.Height, 0);
                  this._controller.CollectionView.ContentInset = contentInsets;
                  this._controller.CollectionView.ScrollIndicatorInsets = contentInsets;
              }
              

              细胞消失的问题完全消失了。这是与 xamarin 合作的 C#,但我希望它可以帮助其他人。

              【讨论】:

                【解决方案8】:

                在我的情况下(垂直滚动,单元格在第一个视图中消失),由于估计大小不正确,单元格正在消失。看来,UICollectionView 使用估计的大小来计算要在第一个视图中加载的项目。我将估计大小设置得太高,这会导致在第一个屏幕中加载的项目数计算错误。

                当我将估计的高度调低时,所有单元格都正确显示。

                【讨论】:

                  【解决方案9】:

                  任何人提供的解决方案都没有帮助我实现我们应用中需要的自定义布局。 相反,我必须这样做:(是的,IT WORKS!!!)

                  - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect{
                      CGSize size = [self collectionViewContentSize];
                      rect.size.height = size.height*2;
                      NSArray *atrributes_Super = [super layoutAttributesForElementsInRect:rect];
                      return atrributes_Super;
                  }
                  

                  毕竟,UICollectionView 只是在寻找要显示在屏幕矩形中的元素的属性。

                  【讨论】:

                  • 这里发生了类似的事情。我的 layoutAttributesForElementsInRect 实现没有返回所需单元格的属性,而后者又被设置为 .hidden = YES。
                  【解决方案10】:

                  上面的答案对我不起作用,但下载图片后,我替换了代码 [self.myCollectionView reloadData][self.myCollectionView reloadSections:[NSIndexSet indexSetWithIndex:0]]; 刷新collectionview并显示所有单元格,你可以试试。

                  【讨论】:

                  • 愚蠢的是,这对我也有用...UICollectionView 是怎么回事?
                  • 尝试了上面的其他解决方案,都没有工作(Swift 3),这个修复了这个错误。奇怪...
                  • 不敢相信这真的有效,它也为我添加了动画。
                  • 有时一些随机单元格也会消失:/
                  • 对我来说,这使单元格重新出现,但是当用户滚动过去然后回到该点时它们又消失了
                  【解决方案11】:

                  那么,什么起作用了?

                  1) 子类UICollectionViewFlowLayout

                  2) 将我的 UICollectionView 的 flowLayout 设置为我的新子类。

                  3) 在UICollectionViewFlowLayout子类的init方法上,设置你想要的方向:

                  self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
                  

                  在我的例子中是水平的。

                  4) 重要部分

                  -(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
                  {
                     return YES;
                  }
                  

                  此时,我应该稍微推理一下,但老实说,我没有头绪。

                  【讨论】:

                  • 看看这个bug:openradar.appspot.com/12433891会不会是你遇到的问题?
                  • 老实说Rob,使用UICollectionView时会发生奇怪的事情,不确定是否相关。
                  • 你试过调整单元格的宽度和高度吗?我在水平滚动的集合视图中遇到了同样的渲染问题。当我的单元格宽度为 70 且高度为 70 时,单元格会消失。如果我将单元格宽度保持在 70 并将单元格高度更改为 69,则它会正确呈现。我每次都能重现这种情况。
                  • @BryanLuby 在完成了我在shouldInvalidateLayoutForBoundsChange:中所做的工作之后,它运行良好。
                  • 不幸的是,这对我不起作用,但这里的解决方案确实 -> stackoverflow.com/questions/12927027/… 如果你在该函数中输出矩形,你会看到它创建了两行/两列,所以你必须将其过滤到 1。
                  【解决方案12】:

                  Rob 关于这个错误的提示帮助了我。该错误指出,如果部分插图和单元格的宽度和间距加起来正好等于屏幕的宽度,那么第一列有时会随机消失并在某些地方的某些单元格中重新出现。我没有子类化或更改单元格宽度,而是将故事板中左右的部分插图从 6 更改为 4,但我再也没有看到问题。

                  【讨论】:

                  • 我无法使用 Rob 的解决方案修复它。但我真的很高兴它对你有用。
                  猜你喜欢
                  • 2023-03-25
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2018-11-15
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多