UIViewController 里面的 CollectionViewCell 内存问题
UIViewController inside CollectionViewCell memory problem
我在 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
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()
方法中删除了子视图。
请帮我找出问题。
问题是每次单元格出列时您都在创建一个新的 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 的场景。
我认为这是问题所在
addChild(viewColtroller) //1
viewColtroller.view.frame = cell.contentView.bounds
cell.contentView.addSubview(viewColtroller.view)
viewColtroller.didMove(toParent: self)
(1*) self (UIViewController) 强烈保留 "child" ViewController
当您 prepareForReuse 单元格时,您只是从层次结构中删除 "childViewController" 视图,但 "childViewController" 本身仍由 UIViewController (parent).
当您将一个新单元格出队时,您重复该过程,创建一个新的 child 并将其添加到 parent 而不删除前一个
viewController.removeFromParentViewController()
,所以 child 没有被释放。这增加了每个单元格出列的内存(实际上每个新的 childViewController 添加到 parent)。
确认这一点的一个好方法是在 "child" viewcontroller deinit 方法上放置一个断点。
deinit {
// Breakpoint here
print("DEINIT")
}
注意:这里的打印是必须的,空方法不会捕获断点。
此外,要调试它,您可以在添加新的 child
之前打印 childViewControllers
print(self.childViewControllers)
因此,在简历中,这里的问题是 cildViewController 被 "parent" 保留,而您在每次出队时添加新的。
希望对您有所帮助,抱歉回复太长了。
我在 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
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()
方法中删除了子视图。
请帮我找出问题。
问题是每次单元格出列时您都在创建一个新的 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 的场景。
我认为这是问题所在
addChild(viewColtroller) //1
viewColtroller.view.frame = cell.contentView.bounds
cell.contentView.addSubview(viewColtroller.view)
viewColtroller.didMove(toParent: self)
(1*) self (UIViewController) 强烈保留 "child" ViewController
当您 prepareForReuse 单元格时,您只是从层次结构中删除 "childViewController" 视图,但 "childViewController" 本身仍由 UIViewController (parent).
当您将一个新单元格出队时,您重复该过程,创建一个新的 child 并将其添加到 parent 而不删除前一个
viewController.removeFromParentViewController()
,所以 child 没有被释放。这增加了每个单元格出列的内存(实际上每个新的 childViewController 添加到 parent)。
确认这一点的一个好方法是在 "child" viewcontroller deinit 方法上放置一个断点。
deinit {
// Breakpoint here
print("DEINIT")
}
注意:这里的打印是必须的,空方法不会捕获断点。
此外,要调试它,您可以在添加新的 child
之前打印 childViewControllersprint(self.childViewControllers)
因此,在简历中,这里的问题是 cildViewController 被 "parent" 保留,而您在每次出队时添加新的。
希望对您有所帮助,抱歉回复太长了。