Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIViewController still in memory after calling dismiss

Tags:

ios

swift

So I create a UICollectionViewController class along with a custom UICollectionViewCell. I am presenting a new UIViewController from the CollectionView and then dismissing it in the UIViewController in order to return to the CollectionView. Everything works except for the fact that after dismissing the UIViewController it still remains in memory which is not what I want. I would like to completely destroy the UIViewController once it is dismiss but cannot figure out how do it.

Am I doing anything wrong? Is it normal for the dismiss ViewController to remain in memory after it's dismissal?

// UICollectionViewController class
class MyCollection: UICollectionViewController, UICollectionViewDelegateFlowLayout { 

  let cellId = "cellId"

  override func viewDidLoad() {
    collectionView.register(CustomCell.self, forCellWithReuseIdentifier: cellId)
  }

  let viewControllers:[UIViewController] = [ViewController1()]

  override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

    return viewControllers.count
  }   

  override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let activityCell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! CustomCell

    return activityCell
  }    

  override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

    let vc = viewControllers[indexPath.item]

    present(vc, animated: true, completion: nil)
  }

  func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

    return CGSize(width: view.frame.width, height: 90)
  }    
}

// Custom UICollectionViewCell class
class CustomCell: UICollectionViewCell {

  override init(frame: CGRect) {
    super.init(frame: frame)

    backgroundColor = .red
  }

  required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }
}

class ViewController1: UIViewController {

  lazy var dismissButton: UIButton = {
    let newButton = UIButton(type: .system)
    newButton.setTitle("Dismiss", for: .normal)
    newButton.backgroundColor = .red
    newButton.addTarget(self, action: #selector(dismissView), for: .touchUpInside)
    newButton.translatesAutoresizingMaskIntoConstraints = false
    return newButton
 }()   

 @objc func dismissView() {
   dismiss(animated: true, completion: nil)
 }

  override func viewDidLoad() {
    super.viewDidLoad()

    view.addSubview(dismissButton)

    NSLayoutConstraint.activate([
      dissmissButton.centerXAnchor.constraint(equalTo: view.centerXAnchor)
      dissmissButton.centerYAnchor.constraint(equalTo: view.centerYAnchor)
      ])
  }
}
like image 412
RickyTheCoder Avatar asked Nov 22 '25 03:11

RickyTheCoder


1 Answers

Reason why ViewController1 instance is not destroyed completely?

Even after the viewController is dismissed, you're still holding the reference to it inside MyCollection's viewControllers array.

Solution:

In case, you want a brand new instance of the controller everytime a cell is tapped, there is no need to store the controller in viewControllers array.

Simply update didSelectItemAt method to,

override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    let vc = ViewController1() //here......
    present(vc, animated: true, completion: nil)
}
like image 137
PGDev Avatar answered Nov 24 '25 19:11

PGDev



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!