iOS: Memory leaks and Notifications
Most of the applications allow users to navigate to different parts of the app with ease, internally we developers use, navigation controllers, tabs, modals, replace roots etc to handle these things. Most of the times while doing so, we sometimes tend to expect OS to clean up somethings for us like the viewcontrollers that we popped out or the viewcontrollers that we just replaced in the root etc. But in real world does it happen that way? hmm… yes it can!! but with our help.
One of the common cause of preventing OS to clean up unused stuffs are the Retain Cycles which would mean that there is a cyclic string referencing between objects, usually happens between a Parent and Child, eg: A parent viewcontroller has a strong reference to child viewcontroller and child has a strong reference to its parent. In this case OS cant clean up any of those guys as both are always holding a strong reference.
What this has to do with Notifications?
When we want multiple entities to know that something has happened… we use notifications, most of the time on
viewDidload or appear we see the similar code as below
NotificationCenter.default.addObserver(self, selector: #selector(observerFired), name: NSNotification.Name(rawValue: “NotifFired”), object: nil)
Now ofcourse you know that you should remove the obeservers, but where? most of the time, because of feature needs you end up writing that in
But do we check whether this gets executed? hmm… not always, we kind of expect that yeah when the view is popped out this will happen , if you do not make sure the notifications are unsubscribed, you will end up in executing the
observerFired(from the code block above)method multiplied by the number of times the viewcontroller has loaded on to the screen and lets say if that operation involves an api call or heavy operations, it will have serious impact.
To prevent these behavior the idea is to ensure that
deinitgets called. There are two advantages to that, by ensuring this you can fix issues with notifications and as well as most of the memory leaks.
Below are what I look for when it comes to retain cycles
- Make sure delegates are marked weak
- Self captured in closures, to be made weak or unowned ( not all self need that )
- If a child object has a parent object as its property, try to use weak or unowned
Look for persistent count, you can filter by your app module in the bottom left filter area