当 VoiceOver 打开时,我的 UICollectionView 没有填充任何单元格

My UICollectionView doesn't get populated with any cells when VoiceOver is on

我在 iOS 13.

中遇到了一个特殊的辅助功能问题

我有一个实现为 UICollectionView 的日历。如果打开 VoiceOver,collection 视图是空的 - 它根本不会填充任何 UICollectionViewCells。

我已经覆盖了正确的 UICollectionViewDataSource 调用。 numberOfSectionscollectionView(numberOfItemsInSection) 被调用,returns 更正非零值。但是 collectionView(cellForItemAt) 永远不会被调用。那对我来说没有任何意义;它知道我有多少栏目,有多少物品,但它不关心询问物品。

如果我关闭 VoiceOver,它会调用 collectionView(cellForItemAt) 并正确填充我的 collection 视图。在 iOS 12 中,无论 VoiceOver 是否打开,一切都正常。

我错过了什么,或者我该如何调试它? VoiceOver 的状态如何影响我的 collection 视图是否被填充?

我们向 Apple 代表报告了该问题并得到了回复。发生的事情是,在 iOS 13 中,VoiceOver 向集合视图询问有关比可见矩形更大的信息;这是一项有意的更改,以支持某些类型的集合视图,其内容大小事先未知。所以它调用了我们对 layoutAttributesForElements(in rect:) 的覆盖,其中矩形的 Y 值很大,我们没有任何元素。

我们的解决方法是忽略给定矩形的 Y 值,而是使用 0 的 Y 值。 iOS 然后能够找到我们的集合视图单元格。

我遇到了完全相同的问题,但是 Brian 的回答对我不起作用。相反,我发现是将 UICollectionView 的委托和数据源设置为 nil 导致了这个问题。删除将其设置为 nil 的行修复了它。

我遇到了这个问题(UICollectionView 正常,但打开 VoiceOver 时空白)并且无法在任何地方找到答案(none 我遇到问题的已发布回复)。

我的问题原来是针对垂直 UICollectionView 的,您可以将 contentSize 设置为 (width:0, height:something),并且效果很好。但是使用 VoiceOver 它真的不喜欢那样 width:0 并且不会尝试加载任何东西。修复方法是将宽度设置为任意值,甚至 width:1,突然它会再次开始工作。

iOS 14.2 上的问题(未测试其他 iOS 版本)

看起来苹果出于某种原因将用于 layoutAttributesForElements(in rect: CGRect) 的原点设置为负设备高度。我通过使用规范化代码解决了这个问题。

func normalizeRect(_ rect: CGRect) -> CGRect {
    guard rect.origin.x < 0, rect.origin.y < 0 else { return rect }
    let normalizedSize = CGSize(width: rect.origin.x + rect.width, height: rect.origin.y + rect.height)
    let value = CGRect(origin: .zero, size: normalizedSize)
    return value
}


Example iPhone 12max:
  * expected rect (0.0, 0.0, 428.0, 926.0)
  * given rect (-926.0, -926.0, 1354.0, 2778.0)
  * normalized rect: (0, 0, 428 (-926 + 1354), 1852 (-926 + 2278 == 2 * 926)) 

我遇到了同样的问题,但是之前发布的规范化传入 layoutAttributesForElements(in rect: CGRect) 的矩形的解决方案不起作用(事实上,我们甚至根本没有使用传入的矩形值 --我们实现中的方法签名是 layoutAttributesForElements(in _: CGRect)),也没有像 Kyle 建议的那样直接在 collectionView 上设置 contentSize。

对我来说解决问题的方法是覆盖 UICollectionViewLayout 子类上的 collectionViewContentSize 计算 属性。显然,此方法默认配置为 return .zero,这会在启用画外音时破坏布局。仍在努力弄清楚为什么会发生这种情况,但同时将以下内容添加到 UICollectionViewLayout 子类中解决了问题:

override var collectionViewContentSize: CGSize {
  guard let collectionView = collectionView else { return .zero }
  return collectionView.frame.size
}