If you know about what ARC is and why it leaks memory in the IOS application then you can move on to part 2. Since this is a very long article, referring to the following:
- What is a memory leak in IOS(Memory Leaks)
- Why Memory Leaks
- How ARC can't free up memory
- Memory Leaks in the Closure function
- Possible solutions
- Singleton and static Classes Memory leaks
- Differences between weak and unowned
- Identifying Leaks Using Memory Graph Debugger
- Some Thumbs Rules
Swift uses Automatic Reference Counting(ARC) to track and manage application memory. In most cases, this means that management only works in swift framework automatically, and you don't need to understand how memory management works. ARC automatically frees up memory because when 1 instances of the class will release when it is no longer needed.
Part 1: Memory leaks in IOS
A memory leak occurs when memory is occupied and cannot be released using ARC because it does not distinguish if it is actually used or not. And the most common problem is that we create memory leaks when creating a loop of cycles – mutual holding happens! We'll take a closer look at it below.
When can ARC not free up memory?
Each time you create an object from the class, arc saves information about the memory area that this object uses. When an object needs to be released, how does the ARC know it. To understand this issue we will learn how arc works.
Any initial variable will default to a strong type. (strong is a strong, weak type of constraint). When you create its instance with a strong type, the ARC increases the counting variable to 1. Understand that arc produces 1 variable count = 0, when obj creates it increases to 1, when released, minus 1. Ever this count variable = 0 means that it is no longer needed, and the ARC will automatically release this variable. Let's see the following example:
var referenceOne: Person? = Person()
we create a referenceOne of the Person class. Arc will automatically give it strong memory and increase its count to 1.
var reference2 = referenceOne
After performing the above statement, we create a strong link to the Object Person by assigning the address to reference2. As you can see in the following image, the count = 2 variable is held by two guys with this address.
referenceOne = nil
We remove the strong reference to the referenceOne variable by assigning nil to it. As pictured after the turn back is 1.
reference2 = nil
Similarly, we ignore the strong reference reference to the reference2 variable and the current variable count = 0.
Thus, if the created object has no one to refer to, the ARC will delete from the memory. That's how arc works.
So why does memory leak?
As we understand arc will automatically delete the variable from memory when count = 0, but for some reason count never = 0, so it is impossible to free up memory. Read on!
When does arc try to check the count of 1 RC variable(reference count)
When you work with cocoa or cocoa touch, it simply checks when a function exits the loop on the thread. The law on inspection is as follows:
- If no one references an object, arc frees
- If an object does not have a strong reference to it.
Here's a specific example:
var user: User? = User() //1 reference to user Var todo: Todo? = Todo() //1 reference to todo
As shown below, ARC makes a strong reference to the user and todo.
user?. todo = todo //2 strong reference to todo todo?. associatedUser = user// 2 strong reference to user
The above 2 commands work as follows:
- Increase the RC of the todo todo to 2, the todo has 2 owners, 1 creation and 1 assignment.
- Increase the RC of the user to 2, similar to the above.
user = nil //decrease the RC of the user to 1 todo = nil //reduce RC of todo todo to 1
Ideally, when placing users on nil, RC should be 0. However, at this time, each object is strongly referenced to each other, so it cannot be released. And so we create a strong reference cycle – a circle of strong mutual reference that cannot be released.
There are two solutions, using weak references or unowned references.
Revise the code as follows:
var user: User? = User() //RC = 1 to user Var todo: Todo? = Todo() //RC = 1 to todo
The above statement increases the RC for each variable to 1.
user?. todo = todo //RC = 2 todo todo?. associatedUser = user //RC = 1 to user
RC = 2 strong references to todo, while users with RC = 1 because associatedUser is a weak reference.
user = nil
The user's RC statement is about 0.
ARC checks and removes the user from memory. So the todo has a strong reference to it.
todo = nil
At this time the todo has RC = 0 and is deleted from memory.
Rule: When two objects refer to each other, the reference variable returns weak or unowned.
Memory Leaks in Closure
Memory Leak in Closure = self refers to → object refers to → self
Closure is a function created from within another function (parent function), it can use global variables, local variables of the parent function and its own local variables. And when used, it captures variables and throws them inside its scope.
What is capturing?
- We create 2 variables a,b with 2 different values 20 and 30.
- We create someClosure and captures a, b by strong reference.
- When the someMethodThatTakeClosure method calls closure and it returns 2 total values of a, b captures from the viewDidLoad function. Value is 50
Let's study together in the next article: