Hello friends, in this article we will talk about the most used structures for Swift Memory Management. Earlier, I talked about how ARC works. You can find that article here. While creating variables in Swift programming language, you can create 3 different types of variables. These; Strong, Weak and Unowned.
Strong
When you create a variable, its type is Strong by default. A variable of type Strong increases the reference count by 1 in Swift’s ARC structure. This variable is not deleted from RAM unless this increment is 0. Therefore, a Memory Leak may occur.
Weak
When you create a weak type variable, it does not increase the reference number from the ARC structure by 1. For this reason, a Retain Cycle situation will not be in question, so it is easily deleted from the memory. The variable must be optional when creating a weak reference.
Unowned
It has a weak-like structure. The difference is that it is nonoptional. For this reason, a value must be given when creating the variable.
In the example we will do below, we will create a Memory Leak and then provide its solution. In our example, let’s have a customer class and a credit card class. Every customer can have a credit card, and every credit card must have a customer. After defining the classes, I can follow the output by running the print functions on the init and deinit functions.
Let’s not forget that memory leak can only occur in reference type variables. For this reason, there is no memory leak in value type variables such as struct or enum.
After creating our classes, I create a customer and credit card and set them to the classes I created. After I’m done, I set these variables to nil and wait for them to be deleted from RAM, but we see that the functions we put in the Deinit function do not work. The reason is that the reference number cannot be 0. In the example below, I wrote the reference numbers as comments.
import UIKit class Customer { let name: String var creditCard: CreditCard? init(name: String) { self.name = name print("Customer \(name) initialized") } deinit { print("Customer \(name) deinitialized") } } class CreditCard { let creditCardName: String var customer: Customer? init(creditCardName: String) { self.creditCardName = creditCardName print("CreditCard \(creditCardName) initialized") } deinit { print("CreditCard \(creditCardName) deinitialized") } } var customerOmer: Customer? var creditCardTest: CreditCard? customerOmer = Customer(name: "Omer Sezer") // customerOmer's reference count = 1 creditCardTest = CreditCard(creditCardName: "Test Credit Card") // creditCardTest's reference count = 1 customerOmer?.creditCard = creditCardTest // creditCardTest's reference count = 2 creditCardTest?.customer = customerOmer // customerOmer's reference count = 2 customerOmer = nil // customerOmer's reference count = 1 creditCardTest = nil // creditCardTest's reference count = 1
Although I set the variables I created to nil, they are not deleted from RAM and remain in RAM even though I will never use them again. This way, imagine that many of our variables are not used internally and are sitting idle in RAM. After a while, the application will start to contract and the phone will start to warm up. For this reason, we must consider these when creating a variable.
As a solution, we have to establish the logic of the structure here. Every credit card must have a customer, but not every customer has to have a credit card. So we can define the credit card variable in the Customer class as weak . Since the reference of the variable we define as weak will not increase by 1, it will be deleted from the RAM and prevent a Memory Leak from occurring.
import UIKit class Customer { let name: String weak var creditCard: CreditCard? init(name: String) { self.name = name print("Customer \(name) initialized") } deinit { print("Customer \(name) deinitialized") } } class CreditCard { let creditCardName: String var customer: Customer? init(creditCardName: String) { self.creditCardName = creditCardName print("CreditCard \(creditCardName) initialized") } deinit { print("CreditCard \(creditCardName) deinitialized") } } var customerOmer: Customer? var creditCardTest: CreditCard? customerOmer = Customer(name: "Omer Sezer") // customerOmer's reference count = 1 creditCardTest = CreditCard(creditCardName: "Test Credit Card") // creditCardTest's reference count = 1 customerOmer?.creditCard = creditCardTest // creditCardTest's reference count = 1 creditCardTest?.customer = customerOmer // customerOmer's reference count = 2 creditCardTest = nil // creditCardTest's reference count = 0 customerOmer = nil // customerOmer's reference count = 0
More information can be found here. If you have questions, you can reach them by sending an e-mail or comment.
Comments (6)
zoritoler imolsays:
Friday February 3rd, 2023 at 07:04 AMI admire your piece of work, thanks for all the useful content.
Evden Eve Nakliyatsays:
Friday February 17th, 2023 at 09:36 AMHocam yazınız çok güzel bir kaynak oldu teşekkürler ancak web sitesinden görünen kodlarınıza “highlight code” bir tasarım kullanabilirseniz, kodlarınız daha iyi görünür bizim içinde daha okunur olacaktır. Emeğiniz için teşekkürler
omersezersays:
Sunday February 26th, 2023 at 12:25 PMÇok teşekkürler geri bildirim için. Bir güncellemeden sonra oldu. En kısa zamanda düzelteceğiz.
Melih Özmensays:
Sunday February 19th, 2023 at 08:51 PMgüzel anlatım. teşekkürler.
Tuba Hanımsays:
Monday February 27th, 2023 at 02:37 PMHocam Xamarin mi? Flutter mı? React Native mi? Swift mi? karar veremedim bir türlü. Bu konu hakkında da bir yazı yazar mısınız?
omersezersays:
Monday February 27th, 2023 at 10:52 PMSelam, yakın zamanda tecrübelerimi anlatacağım bir yazı yazarım. Umarım faydalı olur.