【发布时间】:2017-06-08 19:32:45
【问题描述】:
当使用UICollectionViewFlowLayout 的子类在具有现有补充视图的集合视图中插入多个自定义补充视图时,集合视图似乎会创建故障动画或无法正确处理插入。
插入一个补充视图的行为与预期相同,但一次插入两个补充视图会导致明显的视觉故障,并且一次插入多个补充视图(例如 4+)会使故障恶化。 (iOS 10.2、iOS 9.3、Swift 3、Xcode 8.2.1)
这是一个演示:
您可以使用this sample project 重现该问题。在这个简化的示例中,每个项目都有一个补充视图,并且在每次批量更新期间插入两个项目(具有两个补充视图)。在我的实际项目中,我的补充视图比项目少,并且我利用了其他流布局功能。
我最好的猜测是某些东西导致集合视图混淆了与现有/插入的补充视图相对应的索引路径或布局属性。如果这被证明是 Apple 课程中的一个错误,我将非常感谢您提供最优雅的解决方法。
尝试的解决方案
我已尝试并仔细检查了以下各项:
实现
indexPathsToInsertForSupplementaryView(ofKind:)——据我所知,这很简单,而且我的实现返回了正确的索引路径。始终插入视图。对于补充页眉和页脚视图,UICollectionViewFlowLayout 似乎返回了一个排序后的索引路径数组,但排序数组对我来说没有任何区别。提供初始和最终布局属性——为这些方法调用
super似乎返回了正确的帧,因此不清楚可以对初始或最终布局属性来解决问题。但是请参阅下面提到的第三个好奇心。使布局无效——无论是在
performBatchUpdates()之前、期间或之后手动使布局全部或部分无效,还是完全无效,似乎都没有区别。自定义索引路径——尽管据我所知,补充元素的索引路径不需要与项目索引路径相对应,并且尽管有相反的文档,但 UICollectionViewFlowLayout 会崩溃(通过为不存在的索引路径请求布局属性)除非同类的补充元素从 0 开始按顺序编号。我假设这是集合视图和/或布局对象在插入元素时能够计算新索引路径的方式或删除(即通过增加或减少索引路径的
item属性)。所以构建任意索引路径不是一种选择。
调试时发现的好奇心
视觉故障是补充视图特有的,插入的项目不会发生,即使索引路径和帧对于两者来说都是相同的。
调试视图层次结构发现,虽然插入的补充视图的框架是正确的,但一些现有补充视图的框架是不正确的。尽管布局对象为这些索引路径上的现有视图返回的帧似乎是正确的,但情况仍然如此。
当插入多个补充视图时,集合视图对初始和最终布局属性的调用似乎不平衡。也就是说,对于同一个索引路径,初始布局属性被多次请求(当然,每次都返回相同的属性),对最终布局属性的请求较少。此外,对于一些现有的补充视图,根本不会请求初始和最终布局属性。我觉得这很可疑。这让我相信集合视图在某种程度上混淆了更新前后的补充视图和/或索引路径。
我的 Swift 代码创建的 IndexPath 实例的内存地址与 UICollectionView 和 UICollectionViewFlowLayout 在内部创建的 NSIndexPath 实例的内存地址截然不同。前者总是不同的(如预期的那样),而后者在启动之间似乎是相同的(例如 [0, 0]、[0, 1] 和 [0, 2] 总是在
0xc000000000000016、0xc000000000200016和 @ 987654341@)。在 Swift 中,IndexPath 桥接到 NSIndexPath,但 the former is a value type whereas the latter is a reference type。 NSIndexPath 也是uses tagged pointers。两者之间的桥接不完善和/或集合视图类在内部以某种方式依赖于 NSIndexPath 行为的可能性很小,这会导致此处明显的索引路径混淆。我不知道如何对此进行测试或进一步研究。
类似问题
以下问题可能是相关的,尽管没有一个答案对我有用:
How can UICollectionView supplementary views be inserted or deleted correctly
layoutAttributesForSupplementaryViewOfKind:atIndexPath: passes in incorrect indexPath
UICollectionView supplementary views won't animate “in” or “out”
UICollectionView Decoration and Supplementary views can not be moved
这个问题也可能与 Open Radar 上的this bug report 有关。不过,该报告附带的示例项目有点过于复杂,没有多大用处。
Apple 技术支持
发布此问题后,我向 Apple 提交了技术支持事件。苹果开发者支持回复如下:
我们的工程师已审核您的请求,并确定最好将其作为错误报告处理。
请使用错误报告工具https://developer.apple.com/bug-reporting/ 提交有关此问题的完整错误报告。
...
我们花了一些时间调查解决方法的可能性,但不幸的是空手而归。请跟进您的错误。如果我们将来发现某种解决方法的可能性,我们将伸出援手。抱歉,我没有更好的消息。
如果您遇到此问题,请复制rdar://30510010。
【问题讨论】:
-
看起来像是 UICollectionView 错误的一部分。
-
尝试使用 Bolts 库中的块依赖项(承诺实现)将一个插入链接到下一个插入。这应该避免同时插入故障,并且看起来更自然。
-
您找到解决方法了吗?我也在为同样的事情苦苦挣扎,还时不时断言全局索引失败
标签: ios swift animation uicollectionview uicollectionviewlayout