当使用UICollectionViewFlowLayout的子类在具有现有补充视图的集合视图中插入多个自定义补充视图时,集合视图似乎会创建出色的动画或者无法正确处理插入.
插入一个补充视图的行为与预期相同,但一次插入两个补充视图会导致明显的视觉故障,并且一次插入许多补充视图(例如4+)会使故障恶化.(iOS 10.2,iOS 9.3,Swift 3,Xcode 8.2.1)
这是一个演示:
您可以使用此示例项目重现该问题.在该简化示例中,每个项目有一个补充视图,并且在每个批次更新期间插入两个项目(具有两个补充视图).在我的实际项目中,我的补充视图少于项目,我使用其他流程布局功能.
我最好的猜测是,某些东西导致集合视图混淆了与现有/插入的补充视图相对应的索引路径或布局属性.如果这是Apple课程中的一个错误,我将非常感谢您最优雅的解决方法.
试图解决方案
我试过并仔细检查以下各项:
实现 -indexPathsToInsertForSupplementaryView(ofKind:)
据我所知,这很简单,我的实现返回正确的索引路径.始终插入视图.对于补充页眉和页脚视图,UICollectionViewFlowLayout似乎返回索引路径的排序数组,但对数组进行排序对我没有任何影响.
提供初始和最终布局属性 - super
为这些方法调用似乎返回正确的帧,因此对初始或最终布局属性进行哪些调整(如果有)以解决问题并不明显.但请看下面提到的第三个好奇心.
使布局无效 -it似乎完全没有区别是布局是在全部或部分之前,期间,之后performBatchUpdates()
,还是根本手动无效.
自定义索引路径 - 尽管补充元素的索引路径不需要对应于项索引路径,但据我所知,尽管文档相反,UICollectionViewFlowLayout将崩溃(通过请求不存在的索引路径的布局属性),除非相同类型的补充元素从0开始按顺序编号.我假设这是集合视图和/或布局对象在插入或删除元素时(即通过递增或递减item
索引的属性)计算新索引路径的方式路径).因此,构建任意索引路径不是一种选择.
调试时注意到了好奇心
视觉故障特定于补充视图,并且对于插入的项目不会发生,即使索引路径和帧对于两者都相同.
调试视图层次结构表明,虽然插入的补充视图的帧是正确的,但是一些现有补充视图的帧不正确.尽管布局对象为这些索引路径上的现有视图返回的帧看起来是正确的,但事实仍是如此.
插入多个补充视图时,集合视图对初始和最终布局属性的调用似乎是不平衡的.也就是说,对于相同的索引路径,多次请求初始布局属性(当然,每次都返回相同的属性),并且对最终布局属性的请求较少.此外,对于一些现有的补充视图,根本不会请求初始和最终布局属性.我觉得这很可疑.它让我相信集合视图在更新之前和之后会以某种方式混淆补充视图和/或索引路径.
我的Swift代码创建的IndexPath实例的内存地址与UICollectionView和UICollectionViewFlowLayout内部创建的NSIndexPath实例截然不同.前者总是不同(如预期的那样),而后者在发射之间看起来是相同的(例如[0,0],[0,1]和[0,2]总是在0xc000000000000016
,0xc000000000200016
和0xc000000000400016
).在Swift中,IndexPath桥接到NSIndexPath,但前者是值类型,而后者是引用类型.NSIndexPath还使用标记指针.很可能两者没有完全桥接和/或集合视图类内部依赖NSIndexPath行为以某种方式导致索引路径混淆.我不知道如何测试这个或进一步.
类似的问题
以下问题可能有关,但没有一个答案对我有用:
如何正确插入或删除UICollectionView补充视图
layoutAttributesForSupplementaryViewOfKind:atIndexPath:传入不正确的indexPath
UICollectionView补充视图不会为"in"或"out"设置动画
无法移动UICollectionView装饰和补充视图
该问题也可能与Open Radar上的此错误报告有关.该报告附带的示例项目有点过于复杂而无法使用.
Apple技术支持
发布此问题后,我向Apple提交了技术支持事件.Apple Developer Support回复如下:
我们的工程师已经审核了您的请求,并确定最好将其作为错误报告处理.
请使用https://developer.apple.com/bug-reporting/上的错误报告工具提交有关此问题的完整错误报告.
...
我们花了一些时间调查解决方法的可能性,不幸的是空手而归.请跟进你的错误.如果我们将来发现某种解决方法的可能性,我们会伸出援助之手.对不起,我没有更好的消息.
如果您遇到此问题,请复制rdar:// 30510010.