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 useweak
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 theNotificationCenter
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 useweak 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 yourViewController
, 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