启用VoiceOver时,我的UICollectionView没有填充任何单元格

时间:2019-10-10 20:42:43

标签: ios swift uicollectionview accessibility voiceover

我在iOS 13中遇到了一个特殊的可访问性问题。

我有一个实现为UICollectionView的日历。如果VoiceOver处于打开状态,则集合视图为空-根本不会填充任何UICollectionViewCells。

我已经重写了正确的UICollectionViewDataSource调用。 numberOfSectionscollectionView(numberOfItemsInSection)被调用,并返回正确的非零值。但是collectionView(cellForItemAt)从未被调用。那对我来说毫无意义。它知道我有多少节,有多少件物品,但是不必问这些物品。

如果我关闭VoiceOver,它将调用collectionView(cellForItemAt),并正确填充我的收藏夹视图。在iOS 12中,无论VoiceOver是否打开,一切都可以正常工作。

我缺少什么,或者如何调试? VoiceOver的状态如何影响我的收藏夹视图是否被填充?

4 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

我遇到了这个问题(UICollectionView正常,但是在VoiceOver上为空白)并且在任何地方都找不到答案(我所遇到的问题都没有发布的回复)。

我的问题原来是对于垂直UICollectionView,您可以将contentSize设置为(width:0, height:something),并且可以完美地工作。但是启用VoiceOver确实不喜欢width:0,并且不会尝试加载任何内容。解决方法是将宽度设置为任何值,甚至width:1,然后突然又可以开始工作。

在iOS 14.2上发布(未测试其他iOS版本)

答案 2 :(得分:0)

我们向苹果代表报告了该问题,并得到了答复。发生的事情是,在iOS 13中,VoiceOver会向集合视图询问有关大于可见区域的信息。这是有意的更改,以支持某些类型的集合视图,这些视图的内容大小事先未知。因此,它调用了我们对layoutAttributesForElements(in rect:)的覆盖,并为rect设置了较大的Y负值,而我们那里没有任何元素。

我们的解决方法是忽略给出的rect的Y值,而是使用0的Y值。然后,iOS可以找到我们的收藏夹视图单元格。

答案 3 :(得分:0)

看起来苹果出于某种原因将用于 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))