UIViewController внутри проблемы памяти CollectionViewCell - PullRequest
0 голосов
/ 26 октября 2018

Я отображаю UIViewController внутри UICollectionViewCell. Одна ячейка на страницу. Проблема в том, что когда я провожу пальцем, чтобы перейти на следующую страницу, память продолжает увеличиваться и никогда не возвращается.

Вот соответствующий код.

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")
            }
        }
    }
}

Я полагаю, что проблема заключается в добавлении SubViews в каждую ячейку, но я также удаляю subViews в методе perpareForReuse().

Пожалуйста, помогите мне определить проблему.

Ответы [ 2 ]

0 голосов
/ 26 октября 2018

Я думаю, что это проблема

addChild(viewColtroller)  //1
viewColtroller.view.frame = cell.contentView.bounds
cell.contentView.addSubview(viewColtroller.view)
viewColtroller.didMove(toParent: self)

(1 *) self (UIViewController) сильно сохраняет «дочерний» ViewController

Когда вы подготавливаете ячейку для повторного использования, вы только удаляете представление «childViewController» из иерархии, но сам «childViewController» все еще сохраняется UIViewController (parent).

Когда вы удаляете новую ячейку из очереди, вы повторяете процесс, создавая нового дочернего элемента и добавляя его в родительский БЕЗ, удаляя предыдущий

viewController.removeFromParentViewController()

, поэтому дети не освобождены. Это увеличивает объем памяти с каждой очищенной ячейкой (фактически каждый новый childViewController добавляется к родительскому элементу).

Хороший способ подтвердить это - установить точку останова для метода deinit дочернего viewcontroller.

  deinit {
// Breakpoint here
print("DEINIT")
}

ПРИМЕЧАНИЕ: печать здесь обязательна, пустой метод не перехватит точку останова.

Кроме того, для его отладки вы можете напечатать childViewControllers, прямо перед добавлением нового дочернего элемента

print(self.childViewControllers)

Итак, проблема в том, что cildViewControllers удерживается «родителем», а вы добавляете новые в каждую очередь.

Надеюсь, что это поможет, и извините за длину ответа.

0 голосов
/ 26 октября 2018

Проблема в том, что вы создаете новый 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 в качестве subview collectionViewCell кажется странной вещью, которую нужно сделать. Если у вас нет очень веских причин для этого, я бы порекомендовал просто использовать PageCollectionViewCell и полностью забыть о NewsTableVC.

Я не знаю, чего вы пытаетесь достичь, но трудно представить сценарий, в котором имеет смысл использовать collectionViewCell таким образом.

...