如何保持 CollectionView 单元格返回查看
Posted
技术标签:
【中文标题】如何保持 CollectionView 单元格返回查看【英文标题】:How to keep CollectionView cells on return to view 【发布时间】:2017-07-10 04:00:51 【问题描述】:我有一个 CollectionView,它的单元格对应于 Firebase 数据库中的子项。我的问题是,当我转入另一个视图,然后转回时,CollectionView 单元格消失了。
我有一个 cellForItemAt 函数:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "playerItem", for: indexPath) as! PlayerCollectionViewCell
cell.setupViews(parentSize: Int(self.playerCollectionView.frame.width), hostUID: self.currentUID, tempUserName: playerArrayList[indexPath.item])
cell.layer.cornerRadius = 6
cell.layer.borderWidth = 2
return cell
我还有另一个代码片段:
for i in 0..<playerArrayList.count
print(playerCollectionView.numberOfItems(inSection: 0))
//playerCollectionView.insertItems(at: [IndexPath(item: i, section: 0)])
let cell = playerCollectionView.cellForItem(at: IndexPath(item: i, section: 0)) as! PlayerCollectionViewCell
cell.tempUserName = playerArrayList[i]
cell.setupViews(parentSize: Int(self.playerCollectionView.frame.width), hostUID: self.currentUID, tempUserName: playerArrayList[i])
我仍在学习 CollectionView 如何创建单元格,以及当 View 处于休眠状态时程序会做什么,但我相信我的问题是 cellForItemAt 函数在第一次创建视图时创建了所有单元格并且不会发生之后再次。 我确信这一点,因为当第一次创建视图时,有三个单元格(这正是数据库中有多少孩子)但是当回到同一个视图时,没有单元格。 我试图通过删除所有单元格然后重新制作它们来解决这个问题。 在代码sn-p中,可以看到注释行:
playerCollectionView.insertItems(at: [IndexPath(item: i, section: 0)])
但是这给了我错误:
由于未捕获的异常'NSInternalInconsistencyException'而终止应用程序,原因:'无效更新:第0节中的项目数无效。更新后现有节中包含的项目数(3)必须等于项目数更新前包含在该部分中 (3),加上或减去从该部分插入或删除的项目数(0 插入,1 个删除),加上或减去移入或移出该部分的项目数(0 移入, 0 移出)。'
我也试过用它来创建单元格:
let cell = playerCollectionView.dequeueReusableCell(withReuseIdentifier: "playerItem", for: IndexPath(item: i, section: 0)) as! PlayerCollectionViewCell
但我得到了同样的错误。如何在返回视图时重新创建单元格?
【问题讨论】:
你是怎么回去的?您确定您不会继续使用原始视图控制器的新实例吗? @Paulw11 我正在切换的两个视图在同一个堆栈中,所以我很确定它不是一个新实例。 drive.google.com/file/d/0B5SQeKTVAsVbSEFweEw0dURVejQ/… segues 本身是从视图控制器到视图控制器而不是按钮到视图控制器,因为我需要在 segue 之前执行操作。 如果您没有在导航控制器中使用“后退”按钮,那么您必须确保使用展开转场,否则您会不断推送视图控制器的新实例。在viewDidLoad
中放置一个日志语句或断点,如果它被多次调用,那么您正在创建一个新实例。
@Paulw11 我正在使用后退按钮,并且我使用 print 语句来确定 viewDidLoad 被多次调用。如何恢复第一个实例或终止后退按钮上的当前实例?我正在使用从主菜单视图到当前视图的显示转场,而不是按钮转场。我需要改变segue的类型吗?如果有的话是什么类型的?
【参考方案1】:
检查您是否在 UICollectionViewDataSource
对象中实现方法 collectionView(_:numberOfItemsInSection:)
和 collectionView(_:cellForItemAt:)
。
当使用cellForItem
访问单元格时,您应该检查您是否真的得到了一个单元格。该方法只返回可见单元格。
if let cell = self.playerCollectionView.cellForItem(at: indexPath) as? PlayerCollectionViewCell
cell.tempUserName = playerArrayList[i]
cell.setupViews(parentSize: Int(self.playerCollectionView.frame.width), hostUID: self.currentUID, tempUserName: playerArrayList[i])
你应该有一个集合视图的委托,而不是再次插入单元格,它告诉有多少项目要显示
override function viewDidLoad()
super.viewDidLoad()
playerCollectionView.dataSource = self
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
return playerArrayList.count
insertItemsAt
方法要求您更新来自 numberOfItemsInSection
的返回值以匹配新的项目数。
如果playerArrayList
对象需要重新加载,您可以执行该生命周期方法
override func viewWillAppear(_ animated: Bool)
super.viewWillAppear(animated)
// reload
【讨论】:
我已经添加了 if 语句来检查我是否收到了一个单元格,并且我已经添加了一个重新加载到 viewWillAppear。我已经有了 numberOfItemsInSection 函数,但我没有提到它,因为我不相信这是问题所在。好消息是我没有收到任何错误,但是现在有两倍的单元格。数组 playerArrayList 只有 3 个项目,但 Collection View 中有 6 个单元格。可能是什么问题呢? @米卡 好的,我们已经完成了一半 :) 我无法从此处提供的代码中判断可能是什么问题。也许查看 cell.setupViews 方法中的代码并检查它是否清除了任何视图,或者之前对该方法的调用可能已添加。此外,搜索重复集合视图单元格的答案可能会提供单元格重复的典型情况。【参考方案2】:你想在 viewWillAppear 方法中重新加载集合视图
【讨论】:
以上是关于如何保持 CollectionView 单元格返回查看的主要内容,如果未能解决你的问题,请参考以下文章
从popover返回后如何在collectionview单元格中填充文本字段
一个collectionview单元格中有两个UIImage?