iOS (Swift): Collection View indexPath(for: cell) 对于非可见单元格为 nil
iOS (Swift): Collection View indexPath(for: cell) is nil for non visible cell
我有一个 UIViewController
,它用 Object
:
类型的数组填充 UICollectionView
class MyViewController: UIViewController {
let objects: [Object]!
weak var collectionView: UICollectionView!
func object(for cell: MyCell) {
guard let indexPath = self.collectionView.indexPath(for: cell) else { fatalError("No cell at index path") }
}
}
collectionView
个单元格表示为:
class MyCell: UICollectionViewCell {
weak var delegate: MyCellDelegate?
override func apply(_ layoutAttributes: UICollectionViewLayoutAttributes) {
super.apply(layoutAttributes)
let obj = self.delegate?.object(for: self)
// configure various subviews with obj ...
}
}
它有一个 delegate
与 MyViewController
对话以获得 Object
代表的实例:
protocol MyCellDelegate: class {
func object(for cell: MyCell) -> Object
}
当我在单元格之间向下滚动时,这工作正常,但是,当调用 apply(_ layoutAttributes: UICollectionViewLayoutAttributes)
方法时,对于屏幕外的单元格,它在 guard let indexPath = self.collectionView.indexPath(for: cell) ...
处崩溃。
有办法解决这个问题吗?单元格需要知道它们代表的是 Object
的哪个实例,以便视图控制器可以调整模型。
非常感谢您的帮助!
总是假设如果一个单元格在屏幕外,那么集合视图已经回收了它。集合视图不断这样做以保持低内存使用率和高性能。
为了在屏幕外执行一些操作,我经常做的是持有一个单独的对象(视图模型,在 MVVM 中),可见单元格可以附加到该对象上。该对象由我的对象拥有和保留,并且永远不会被回收。如果我需要执行任何屏幕外操作,此对象会执行。
该单元的唯一工作是:
- 显示数据和
- 接收用户输入
两者都要求它可见。
当我创建单元格时,我使用 prepareForReuse
将其与之前的视图模型分离,并在将单元格附加到下一个视图模型之前进行必要的清理。
备用解决方案
如果您只需要索引路径来获取您的特殊对象,您可以简单地使用布局属性中的索引路径。
protocol MyCellDelegate: class {
func object(for indexPath: IndexPath) -> Object
}
class MyCell: UICollectionViewCell {
weak var delegate: MyCellDelegate?
override func apply(_ layoutAttributes: UICollectionViewLayoutAttributes) {
super.apply(layoutAttributes)
let obj = self.delegate?.object(for: layoutAttributes.indexPath)
// configure various subviews with obj ...
}
}
我有一个 UIViewController
,它用 Object
:
UICollectionView
class MyViewController: UIViewController {
let objects: [Object]!
weak var collectionView: UICollectionView!
func object(for cell: MyCell) {
guard let indexPath = self.collectionView.indexPath(for: cell) else { fatalError("No cell at index path") }
}
}
collectionView
个单元格表示为:
class MyCell: UICollectionViewCell {
weak var delegate: MyCellDelegate?
override func apply(_ layoutAttributes: UICollectionViewLayoutAttributes) {
super.apply(layoutAttributes)
let obj = self.delegate?.object(for: self)
// configure various subviews with obj ...
}
}
它有一个 delegate
与 MyViewController
对话以获得 Object
代表的实例:
protocol MyCellDelegate: class {
func object(for cell: MyCell) -> Object
}
当我在单元格之间向下滚动时,这工作正常,但是,当调用 apply(_ layoutAttributes: UICollectionViewLayoutAttributes)
方法时,对于屏幕外的单元格,它在 guard let indexPath = self.collectionView.indexPath(for: cell) ...
处崩溃。
有办法解决这个问题吗?单元格需要知道它们代表的是 Object
的哪个实例,以便视图控制器可以调整模型。
非常感谢您的帮助!
总是假设如果一个单元格在屏幕外,那么集合视图已经回收了它。集合视图不断这样做以保持低内存使用率和高性能。
为了在屏幕外执行一些操作,我经常做的是持有一个单独的对象(视图模型,在 MVVM 中),可见单元格可以附加到该对象上。该对象由我的对象拥有和保留,并且永远不会被回收。如果我需要执行任何屏幕外操作,此对象会执行。
该单元的唯一工作是:
- 显示数据和
- 接收用户输入
两者都要求它可见。
当我创建单元格时,我使用 prepareForReuse
将其与之前的视图模型分离,并在将单元格附加到下一个视图模型之前进行必要的清理。
备用解决方案
如果您只需要索引路径来获取您的特殊对象,您可以简单地使用布局属性中的索引路径。
protocol MyCellDelegate: class {
func object(for indexPath: IndexPath) -> Object
}
class MyCell: UICollectionViewCell {
weak var delegate: MyCellDelegate?
override func apply(_ layoutAttributes: UICollectionViewLayoutAttributes) {
super.apply(layoutAttributes)
let obj = self.delegate?.object(for: layoutAttributes.indexPath)
// configure various subviews with obj ...
}
}