iOS 14.3上的UICollectionViewCompositionLayout错误
我在iOS 14.3上遇到了一个奇怪的布局问题,集合视图使用了iOS 14.3上的UICollectionViewCompositionLayout错误,ios,swift,uicollectionview,uikit,uicollectionviewcompositionallayout,Ios,Swift,Uicollectionview,Uikit,Uicollectionviewcompositionallayout,我在iOS 14.3上遇到了一个奇怪的布局问题,集合视图使用了UICollectionViewCompositionalLayout,在我的案例中与UICollectionViewDiffableDataSource相结合。 问题是当正交部分前面有固有高度部分时,内部\u UICollectionViewOrthogonalScrollerEmbeddedScrollView的位置错误 幸运的是,我能够很容易地重现这个问题。 考虑这个数据源: 私有变量数据源:UICollectionViewDi
UICollectionViewCompositionalLayout
,在我的案例中与UICollectionViewDiffableDataSource
相结合。
问题是当正交部分前面有固有高度部分时,内部\u UICollectionViewOrthogonalScrollerEmbeddedScrollView
的位置错误
幸运的是,我能够很容易地重现这个问题。
考虑这个数据源:
私有变量数据源:UICollectionViewDiffableDataSource!
枚举节:Int、可哈希、可大小写{
案例优先=0
案例二=1
}
为每个部分创建以下布局:
专用扩展部分{
var节:NSCollectionLayoutSection{
切换自身{
案例一:第一:
let itemSize=NSCollectionLayoutSize(宽度维度:。分数宽度(1),高度维度:。估计(50))
let item=NSCollectionLayoutItem(layoutSize:itemSize)
设groupSize=NSCollectionLayoutSize(宽度维度:。分数宽度(1),高度维度:。估计(50))
let group=NSCollectionLayoutGroup.horizontal(layoutSize:groupSize,子项:[项])
let节:NSCollectionLayoutSection=.init(组:组)
返回段
案例二:
让itemSize=NSCollectionLayoutSize(宽度维度:。分数宽度(1),高度维度:。分数高度(1))
let item=NSCollectionLayoutItem(layoutSize:itemSize)
让groupSize=NSCollectionLayoutSize(宽度维度:。绝对(200),高度维度:。绝对(200))
let group=NSCollectionLayoutGroup.horizontal(layoutSize:groupSize,子项:[项])
let节:NSCollectionLayoutSection=.init(组:组)
section.orthogonalScrollingBehavior=.continuous
section.contentInsets=.init(顶部:10,前导:10,底部:10,尾随:10)
section.interGroupSpacing=10
返回段
}
}
}
打破布局的东西是进入.first
部分,包括itemSize
和groupSize
以及估计的高度
您可以在iOS 14.3上看到下面的结果:乍一看布局在视觉上是正确的,但您立即意识到它被破坏了,因为内部滚动视图位于错误的位置。
这意味着水平滚动在蓝色区域发生错误
在iOS 14.2之前运行完全相同的代码可以获得正确的布局。
你对这个问题怎么看?
我是否遗漏了什么,或者可能是UIKit错误
谢谢我们有估计高度的标题,一些带有\u UICollectionViewOrthogonalScrollerEmbeddedScrollView
的部分由于这种回归而完全被破坏。这是一个在我们的案例中有效的解决方案
public final class CollectionView: UICollectionView {
public override func layoutSubviews() {
super.layoutSubviews()
guard #available(iOS 14.3, *) else { return }
subviews.forEach { subview in
guard
let scrollView = subview as? UIScrollView,
let minY = scrollView.subviews.map(\.frame.origin.y).min(),
minY > scrollView.frame.minY
else { return }
scrollView.contentInset.top = -minY
scrollView.frame.origin.y = minY
}
}
}
我们有一个稍微不同的用例,其中带有滚动视图的部分也使用估计的高度,因此我修改了softenhard
的解决方案来调整滚动视图的高度
public final class CollectionView: UICollectionView {
override public func layoutSubviews() {
super.layoutSubviews()
guard #available(iOS 14.3, *) else { return }
subviews.forEach { subview in
guard
let scrollView = subview as? UIScrollView,
let minY = scrollView.subviews.map(\.frame.origin.y).min(),
let maxHeight = scrollView.subviews.map(\.frame.height).max(),
minY > scrollView.frame.minY || maxHeight > scrollView.frame.height
else { return }
scrollView.contentInset.top = -minY
scrollView.frame.origin.y = minY
scrollView.frame.size.height = maxHeight
}
}
}
对我来说,这个问题在iOS14.3
和14.4
中可以重现。现在已在iOS 14.5 beta1中修复
尝试安装最新的Xcode beta版12.5 beta
,并使用运行iOS 14.5的模拟器对其进行测试
Xcode测试版链接:我遇到了同样的问题,而其他答案的解决方法对我来说并不适用
所以我做了这个扩展来确定它是否是有缺陷的iOS版本:
extension UICollectionView {
static var isIosVersionWithSizeEstimationBug: Bool {
if #available(iOS 14.5, *) {
return false
}
if #available(iOS 14.3, *) {
return true
}
return false
}
}
在这种情况下,我用这个来表示绝对高度。它可能不是每个用例的解决方法。但对我来说,这是一个稳定的解决方案:
let height: NSCollectionLayoutDimension = {
let maxPossibleHeight: CGFloat = 280
if UICollectionView.isIosVersionWithSizeEstimationBug {
return .absolute(maxPossibleHeight)
} else {
return .estimated(maxPossibleHeight)
}
}()
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: height)
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1/3), heightDimension: height)
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitem: item, count: 1)
let section = NSCollectionLayoutSection(group: group)
嗨,马特,我们一周前向苹果报告了这个问题,让我们等待答案。当我得到任何更新时,我会不断更新主题。谢谢你的回答。我们遇到了完全相同的问题。当NSCollectionLayoutDimension
的estimatedHeight
设置为高于正在渲染的实际单元格的值时,似乎会发生这种情况。当您将estimatedHeight
设置为最小大小时,它会按预期工作,因此增大比例似乎有效,但减小比例似乎会导致UICollectionViewOrthogonalScrollerEmbeddedScrollView
位置错误。我们目前正在解决这个问题,将estimatedHeight
包装在if#available(iOS 14.3,*){…}else{…}
之间。正在归档一个雷达。大家好,开发人员技术支持人员回答我们,collection view团队已经意识到该漏洞,应该在下一个iOS版本中发布修复程序。遗憾的是,他们没有向我们提供修复程序的预计发布日期。是否为此提交了雷达文件?如果是这样,我想监控一下。我确实向苹果公司提出了一个问题,但它仍然被标记为打开,还没有整理好。我刚刚检查了Xcode 12.4 RC/iOS 14.4 RC,不幸的是问题仍然存在。感谢分享,这似乎很好地解决了问题+1这一个对我们来说也很好,最初看起来像上一个,但由于问题的间歇性,它有时会导致视图发生变化。虽然它修复得更好,但我们仍然间歇性地遇到问题。请更新代码以使用可用的guard}(iOS 14.3,*),否则{return}
而不是此代码,因为它错误的if#available(iOS 14.3,*){return}
谢谢,@EhabSaifan。更新。