CollectionViewCell里面的UIViewController内存问题
Posted
技术标签:
【中文标题】CollectionViewCell里面的UIViewController内存问题【英文标题】:UIViewController inside CollectionViewCell memory problem 【发布时间】:2018-10-26 14:24:12 【问题描述】:我在 UICollectionViewCell 中显示 UIViewController。每页一个单元格。问题是当我滑动到下一页时,内存会不断增加并且永远不会回来。
这里是相关代码。
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
let newsVC: NewsTableVC =
return storyboard?.instantiateViewController(withIdentifier: "NewsListVC")
() as! NewsTableVC
let cell = pagerCollectionView.dequeueReusableCell(withReuseIdentifier: "PageCollectionViewCell", for: indexPath) as! PageCollectionViewCell
//Wraping ViewController in CollectionView Cell
return wrapAndGetCell(viewColtroller: newsVC, cell: cell)
func wrapAndGetCell(viewColtroller: UIViewController, cell: PageCollectionViewCell) -> PageCollectionViewCell
//setting tag to remove view when it's being reused
viewColtroller.view.tag = PageCollectionViewCell.SUBVIEW_TAG
addChild(viewColtroller)
viewColtroller.view.frame = cell.contentView.bounds
cell.contentView.addSubview(viewColtroller.view)
viewColtroller.didMove(toParent: self)
return cell
这里是 collectionViewCell 类
class PageCollectionViewCell: UICollectionViewCell
static let SUBVIEW_TAG: Int = 1000
override func prepareForReuse()
super.prepareForReuse()
let subViews = self.contentView.subviews
for subView in subViews
if subView.tag == PageCollectionViewCell.SUBVIEW_TAG
subView.removeFromSuperview()
print("subView removed")
我想问题在于在每个单元格中添加子视图,但我也在 perpareForReuse()
方法中删除了子视图。
请帮我找出问题。
【问题讨论】:
【参考方案1】:问题在于,每次单元格出列时,您都会创建一个新的NewsTableVC
。您需要做的只是重复使用相同的视图控制器,而不是每次获得一个单元格时都创建一个新的视图控制器。
创建一个[NewsTableVC]
类型的数组,然后这样做:
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
let newsVC = self.newsVCArray[indexPath.item]
let cell = pagerCollectionView.dequeueReusableCell(withReuseIdentifier: "PageCollectionViewCell", for: indexPath) as! PageCollectionViewCell
//Wraping ViewController in CollectionView Cell
return wrapAndGetCell(viewColtroller: newsVC, cell: cell)
这应该可以解决您的内存问题,但是创建将 viewController 的视图添加为 collectionViewCell 子视图似乎是一件奇怪的事情。除非您有充分的理由这样做,否则我建议您只使用 PageCollectionViewCell
,而完全忘记 NewsTableVC
。
我不知道您要完成什么,但很难想象以这种方式使用 collectionViewCell 的场景。
【讨论】:
感谢@LulzCow 它解决了我的问题。基本上我需要在 CollectionView 中显示不同类型的 UIViewControllers。我不能将每个 UIVC 都设为 CollectionViewCell,因为它们在其他地方被重用,这就是我这样做的原因(包装在 CollectionViewCell 中)。如果您认为知道其他更好的方法,请告诉我。【参考方案2】:我认为这是问题
addChild(viewColtroller) //1
viewColtroller.view.frame = cell.contentView.bounds
cell.contentView.addSubview(viewColtroller.view)
viewColtroller.didMove(toParent: self)
(1*) self (UIViewController) 强烈保留“子”ViewController
当您 prepareForReuse 单元格时,您只是从层次结构中删除“childViewController”视图,但“childViewController”本身仍由 UIViewController(父级)保留。
当您将一个新单元格出列时,您会重复该过程,创建一个新子单元并将其添加到父单元,而不会删除前一个单元
viewController.removeFromParentViewController()
,所以孩子不会被释放。这增加了每个单元格出列时的内存(实际上每个新的 childViewController 添加到父级)。
确认这一点的一个好方法是在“子”视图控制器的 deinit 方法上放置一个断点。
deinit
// Breakpoint here
print("DEINIT")
注意:这里的打印是必需的,空方法不会捕获断点。
另外,要调试它,您可以在添加新子之前打印 childViewControllers
print(self.childViewControllers)
因此,在简历中,这里的问题是 cildViewControllers 被“父级”保留,并且您在每个 dequeue 上添加新的。
希望对您有所帮助,对于回复的长度感到抱歉。
【讨论】:
以上是关于CollectionViewCell里面的UIViewController内存问题的主要内容,如果未能解决你的问题,请参考以下文章
CollectionView 里面的 CollectionView | CollectionViewCell 自动布局错误
CollectionViewCell 顶部的按钮使 collectionView 停止滚动
如何为自定义 TableViewCell 和 CollectionView Cell 使用一个 UIView。?