iOS swift UICollectionView在滚动过第一个满屏幕后将丢失单元格约束
我正在尝试学习如何在Swift iOS应用程序中处理UICollectionViews,这只是一个简单的应用程序,它在单元格中显示图像和标签25次。最初,错误的约束阻止CollectionView显示任何内容,但一旦我解决了这些问题,CollectionView就会按照预期显示单元格。根据我的布局方法显示了所有25项的调试消息 然后我向下滚动,一旦它通过了第11项,它似乎完全失去了布局,如下图所示。向上滚动,它更不稳定,所有的单元格都变成了一个完整大小的图像 代码没有什么特别之处,尤其是布局-以下是代码:iOS swift UICollectionView在滚动过第一个满屏幕后将丢失单元格约束,ios,swift,uicollectionview,Ios,Swift,Uicollectionview,我正在尝试学习如何在Swift iOS应用程序中处理UICollectionViews,这只是一个简单的应用程序,它在单元格中显示图像和标签25次。最初,错误的约束阻止CollectionView显示任何内容,但一旦我解决了这些问题,CollectionView就会按照预期显示单元格。根据我的布局方法显示了所有25项的调试消息 然后我向下滚动,一旦它通过了第11项,它似乎完全失去了布局,如下图所示。向上滚动,它更不稳定,所有的单元格都变成了一个完整大小的图像 代码没有什么特别之处,尤其是布局-
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if indexPath.item > 10 {
// Limit number of debug messages
print("view.bounds: \(view.bounds)")
print("collectionView.bounds: \(collectionView.bounds)")
print("collectionView.alignmentRectInsets: \(collectionView.alignmentRectInsets)")
print("collectionView.contentInset: \(collectionView.contentInset)")
}
let width = view.bounds.width
print("width[\(indexPath.item)]: \(width)")
let cellDimension = (width / 2 ) - 15
print("cellDimension[\(indexPath.item)]: \(cellDimension)")
let returnSize = CGSize(width: cellDimension, height: cellDimension)
print("returnSize[\(indexPath.item)]: \(returnSize)")
return returnSize
}
一旦超过第11项,调试器就会开始发出大量的消息:
2019-10-22 01:32:54.794032-0500 CollectionTest#1[13173:339022] The behavior of the UICollectionViewFlowLayout is not defined because:
2019-10-22 01:32:54.794203-0500 CollectionTest#1[13173:339022] the item width must be less than the width of the UICollectionView minus the section insets left and right values, minus the content insets left and right values.
2019-10-22 01:32:54.794360-0500 CollectionTest#1[13173:339022] Please check the values returned by the delegate.
2019-10-22 01:32:54.794856-0500 CollectionTest#1[13173:339022] The relevant UICollectionViewFlowLayout instance is <UICollectionViewFlowLayout: 0x7fe4c1407750>, and it is attached to <UICollectionView: 0x7fe492819400; frame = (0 0; 414 736); clipsToBounds = YES; autoresize = LM+W+RM+TM+H+BM; gestureRecognizers = <NSArray: 0x600000965050>; layer = <CALayer: 0x60000076efe0>; contentOffset: {0, 355}; contentSize: {414, 2512}; adjustedContentInset: {20, 0, 0, 0}> collection view layout: <UICollectionViewFlowLayout: 0x7fe4c1407750>.
2019-10-22 01:32:54.801289-0500 CollectionTest#1[13173:339022] Make a symbolic breakpoint at UICollectionViewFlowLayoutBreakForInvalidSizes to catch this in the debugger.
This just goes on and on ... abbreviated for brevity.
顺便说一下,使用哪个版本的运行时模拟器似乎没有任何区别
在我还有头发要拔的时候,非常感谢您的帮助、指点、建议等。谢谢。尝试将
cellImage
内部CollectionViewCell
的clipToBounds
属性设置为true
,即
class CollectionViewCell: UICollectionViewCell {
@IBOutlet weak var cellImage: UIImageView!
override func awakeFromNib() {
super.awakeFromNib()
self.cellImage.clipsToBounds = true //here..
}
//rest of the code....
}
您还可以在UI本身中设置cellImage
的clipToBounds
,即
注意:在
CollectionViewCell
中移动单元格布局的所有代码,而不是在cellForItemAt
中写入所有内容。这将减少代码的体积和可读性。尝试将cellImage
内部CollectionViewCell
的clipToBounds
属性设置为true
,即
class CollectionViewCell: UICollectionViewCell {
@IBOutlet weak var cellImage: UIImageView!
override func awakeFromNib() {
super.awakeFromNib()
self.cellImage.clipsToBounds = true //here..
}
//rest of the code....
}
您还可以在UI本身中设置cellImage
的clipToBounds
,即
注意:在
CollectionViewCell
中移动单元格布局的所有代码,而不是在cellForItemAt
中写入所有内容。这将减少代码的体积和可读性。谢谢您的建议。我发现了一篇关于堆栈溢出的文章,它将我推向了一个似乎有助于解决问题的方向
我可能是错的,但我的观察结果告诉我,似乎并非所有的单元格都是根据情节提要值初始化大小的。前十几个单元都是这样做的,但当集合视图开始重用/回收单元时,它就无法跟踪单元大小。我尝试在cellForItemAt()中设置单元格大小,但这会导致一些非常糟糕的递归问题
通过调试器观察,sizeForItemAt()只在最初被调用,而不是在单元格开始被重用时,当单元格大小丢失时,各种不希望发生的事情开始发生
在viewDidLoad()中初始化单元格大小消除了大部分问题,也就是说,在设备旋转之前,sizeForItemAt()会在iPhone模拟器中为新布局调用,但不会在iPad模拟器中调用
解决方法是在viewDidLoad()中检查设备类型,并计算每行所需的单元数。如果在设备旋转时希望每行有不同数量的单元格,那么简单地设置布局的单元格大小并不能完全解决问题
至少就目前而言,这似乎已经缓和了问题
我只是有点担心我遗漏了一些东西,因为SizeForestMat()函数没有按预期调用。谢谢你的建议。我发现了一篇关于堆栈溢出的文章,它将我推向了一个似乎有助于解决问题的方向 我可能是错的,但我的观察结果告诉我,似乎并非所有的单元格都是根据情节提要值初始化大小的。前十几个单元都是这样做的,但当集合视图开始重用/回收单元时,它就无法跟踪单元大小。我尝试在cellForItemAt()中设置单元格大小,但这会导致一些非常糟糕的递归问题 通过调试器观察,sizeForItemAt()只在最初被调用,而不是在单元格开始被重用时,当单元格大小丢失时,各种不希望发生的事情开始发生 在viewDidLoad()中初始化单元格大小消除了大部分问题,也就是说,在设备旋转之前,sizeForItemAt()会在iPhone模拟器中为新布局调用,但不会在iPad模拟器中调用 解决方法是在viewDidLoad()中检查设备类型,并计算每行所需的单元数。如果在设备旋转时希望每行有不同数量的单元格,那么简单地设置布局的单元格大小并不能完全解决问题 至少就目前而言,这似乎已经缓和了问题
我只是有点担心我遗漏了一些东西,因为sizeForItemAt()函数没有按预期调用。您是否分别定义了每个项目的大小?另外,在CollectionViewCell类中移动单元格布局的所有代码,而不是在cellForItemAt中编写所有代码。是否分别定义了每个项目的大小?另外,在CollectionViewCell类中移动单元格布局的所有代码,而不是在cellForItemAt中编写所有代码。感谢您的建议,但是“剪裁到边界”已经过检查,似乎没有任何影响。我会在答案区发布我的解决方案。谢谢你的建议,但“剪辑到边界”已经过检查,似乎没有任何影响。我会将我的解决方案张贴在回答区。