我正试图找到处理UICollectionView状态恢复的最佳方法,因为它的元素可能会左右移动。我的目标是确保在重新启动应用程序时,集合视图中的最后一个查看项仍然是可见的,即使这些项目已经移动。例如,当应用程序被杀死时,项目A在索引3的单元格中,当应用程序重新启动时,如果模型说项目A应该显示在索引4处,我希望集合视图在索引4处初始化对单元格的偏移量。
我认为在我的UIDataSourceModelAssociation类中实现UICollectionViewDataSource协议会解决这个问题,就像文档声明的那样:
UITableView和UICollectionView类使用该协议的方法来确保将相同的数据对象(而不仅仅是相同的行索引)滚动到视图中并进行选择。
然而,我观察到的是,在恢复过程中,实现此协议确实会适当地影响所选单元格的indexPath (这对我的应用程序并不重要),但它不会影响滚动位置。滚动位置(集合视图的contentOffset)总是被还原到应用程序被杀死时的确切位置,而不受UICollectionViewDataSource的影响。
我确实有这样的解决办法。它基本上是与模型集合协议相同的模式,但我必须手动完成:
override func encodeRestorableStateWithCoder(coder: NSCoder) {
let identifier = determineIdOfCurrentlyVisibleCell()
coder.encodeObject(identifier, forKey: "visibleCellIdentifier")
}
override func decodeRestorableStateWithCoder(coder: NSCoder) {
if let identifier = coder.decodeObjectForKey("visibleCellIdentifier") as? String {
if let indexPath = model.indexPathForIdentifier(identifier) {
collectionView.scrollToItemAtIndexPath(indexPath, atScrollPosition: .CenteredVertically, animated: false)
}
}
}我是否误解了UIDataSourceModelAssociation的用法?有窃听器吗?是否有更优雅或更正确的方法让这件事起作用?
发布于 2015-04-12 21:34:18
正如您已经指出的,UIDataSourceModelAssociation似乎无法恢复UICollectionView的可见偏移量,但只用于选定的项。我尝试在modelIdentifierForElementAtIndexPath和indexPathForElementWithModelIdentifier上设置断点,并注意到只有在选择单元格之后才调用它们。如果在回滚我的应用程序之前清除了集合视图中选定的单元格,那么modelIdentifierForElementAtIndexPath就不会被调用,但一旦我设置了至少一个选定的单元格,它就会被调用。至少我可以验证,看到这种行为的不仅仅是您。
我认为,由于UICollectionView的不同性质,创建将可见单元格滚动到正确位置的行为可能并不简单,但这一点显然没有反映在苹果的文档中。手动将标识符编码到布局的第一个可见单元格应该是一个很好的选择。我所做的是将集合视图的滚动偏移量包装在一个NSValue中,并恢复该值:
var collectionView: UICollectionView?
// ...
override func encodeRestorableStateWithCoder(coder: NSCoder) {
if let view = collectionView, offsetValue = NSValue(CGPoint: view.contentOffset) {
coder.encodeObject(offsetValue, forKey: CollectionViewContentOffsetKey)
}
super.encodeRestorableStateWithCoder(coder)
}
override func decodeRestorableStateWithCoder(coder: NSCoder) {
if let offsetValue = coder.decodeObjectForKey(CollectionViewContentOffsetKey) as? NSValue {
collectionView?.setContentOffset(offsetValue.CGPointValue(), animated: false)
}
super.decodeRestorableStateWithCoder(coder)
}发布于 2020-02-18 11:43:14
使用CGPoint根据@Ste窗格的建议进行更新。
override func encodeRestorableState(with coder: NSCoder) {
super.encodeRestorableState(with: coder)
coder.encode(collectionView.contentOffset, forKey: "CollectionViewContentOffset")
}
override func decodeRestorableState(with coder: NSCoder) {
super.decodeRestorableState(with: coder)
let offsetValue = coder.decodeObject(forKey: "CollectionViewOffset") as! CGPoint
collectionView?.setContentOffset(offsetValue, animated: false)
}https://stackoverflow.com/questions/28310452
复制相似问题