Reasons for deinit is not getting called iOS Swift

When you pop your ViewController and your deinit is not getting called, it means someone is holding a strong reference of your ViewController. Deinit should call otherwise there is a memory leak and we must fix this. Let’s find out some main reasons for deinit is not being called.

Make a weak variable of your Protocol

Always use weak keyword while making a variable of your Protocol so that when your ViewController released it will also get released. If you don’t make it weak then it will be a strong variable which holds your ViewController strongly and won’t let it release.
protocol MyProtocol: class {
    func updateData()
}

class ViewController: UIViewController {
    
    weak var delegate: MyProtocol? //1
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.delegate = self
    }
    
    deinit {
        print("ViewController deinit")
    }
}

1: We have used weak keywords to make a weak variable of MyProtocol

Use “weak self” inside NotificationCenter closure

Inside the NotificationCenter closure always use weak self or unowned self, otherwise it holds the strong reference of your ViewController causing a memory leak and your deinit will never get called.
NotificationCenter.default.addObserver(forName: NSNotification.Name("notificationName"), object: nil, queue:
OperationQueue.main) { [weak self] notification in //1
    guard let strongSelf = self else { return } //2
    
    strongSelf.updateTask()
    // Write your code and use strongSelf instead of self
}
1 & 2: Here we are using weak self inside the closure so that it won’t capture the strong reference of ViewController.

Use “weak self” inside the Closure

Make a practice that inside every closure always use weak self, using this the strong reference of your ViewController will never get holds, so no more memory leak and your deinit will be call every time.
class ViewController: UIViewController {
    
    var myClosure: (() -> ())?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.myClosure = { [weak self] in
            guard let strongSelf = self else { return }
            // Write your code and use strongSelf instead of self
            print("weak self is: \(strongSelf)")
        }
    }
    
    deinit {
        print("ViewController deinit")
    }
}

Any class should not holds a strong reference of your ViewController

Make sure any other class is not holding the strong reference of your ViewController, it will also cause a memory leak and won’t let your ViewController release and your deinit won’t run.
class MyCustomView: UIView {
    
    weak var viewC: ViewController? //1
}

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let subView = MyCustomView()
        subView.viewC = self
        self.view.addSubview(subView)
    }
    
    deinit {
        print("ViewController deinit")
    }
}

1: As you can see here we are using weak variable of ViewController class so, it will not hold a strong reference of it.

Read our next article: Everything about CAGradientLayer in just 5 mins

Leave a Reply

Your email address will not be published. Required fields are marked *