Quantcast
Channel: Yudiz Solutions Ltd.
Viewing all articles
Browse latest Browse all 595

See how memory can be easily managed in Swift

$
0
0

Does your iOS application takes too much time to load ? or Does it gets hanged during run-time operation ? If yes then it means that your iOS application development lacks in managing memory. While writing a program the main concern should be less memory occupation. This aids in smooth running of application even on devices having lower primary memory.

Swift uses a system of memory management called Automatic Reference Counting (ARC). When you create an object a reference of that object is created in memory. ARC count is then incremented. When the object goes out of scope or is no longer being used then in that case the ARC count gets decremented. ARC handles all this counting automatically. But there are some cases in which manually we need to handle the memory of objects.

Retain cycle and memory leaks

A retain cycle happens when two objects have strong references to each other. In that case none of the object is able to free the occupied memory. In such cases the ARC fails and memory leaks can occur. Take a look at the below example.

Note: Execute the below program in command line application. Do not run it in playground because it maintains the references of variables during code evaluation. So memory management doesn’t behave the same way in a playground as it does outside a playground.


println("Program Starts")
class Animal{
var name:String
var bestFriend:Animal?
init(name: String){
self.name = name
}
deinit{
println("Object with name \(name) is being released")
}
}
var lion:Animal?
var tiger:Animal?
lion = Animal(name: "Lion")
tiger = Animal(name:"Tiger")
lion = nil
tiger = nil
println("Program ends")

This example shows ARC working correctly. When we run this program we will see the following output in the console:

  • Program starting
  • Object with name Lion is being released
  • Object with name Tiger is being released
  • Program ending

We create 2 objects named lion and tiger (they are declared optionals so that we can assign nil to them). Our Animal class has a deinitializer that prints out a message to let us know when objects are being released (line 11). Each of these objects has a reference count of 1 after we assign them to variables (lines 16-17). After assigning the 2 objects to variables lion and tiger, we change both those variables to nil at lines 22-23. Now these variables no longer refer to the two objects, and the reference count for each object decreases by 1. So each now has a reference count of 0 and gets released. In our program output we see that this is the case and the two objects got released once we were no longer referring to them.

The below program introduces a circular dependency that results in a retain cycle.


println("Program starts")
class Animal{
var name:String
var bestFriend:Animal?
init(name: String)
{
self.name = name
}
deinit
{
println("Object with name \(name) is being released")
}
}
var lion:Animal?
var tiger:Animal?
lion = Animal(name: "Lion")
tiger = Animal(name:"Tiger")
tiger?.bestFriend = lion
lion?.bestFriend = tiger
lion = nil
tiger = nil
println("Program ending)

Output:

  • Program starting
  • Program ending

This time our objects didn’t get released. Lets walk through this example with memory management in mind. At lines 19 and 20 we assign Animal objects to vars lion and tiger. At this point each of these objects has a reference count of 1. Now at lines 22 and 23 we set lion as tigers best friend and tiger as lions best friend. So now lions bestFriend property points at the same object as the variable tiger and the reference count for that object is 2. And tiger’s best Friend property points at the same object as the variable lion and that object’s reference count is also 2.

Now at lines 25 and 26 we set both lion and tiger to nil. Both of the objects that these variables were pointing to get their reference count decreased by 1. But both currently have a reference count of 2, so decreasing by 1 means that their reference count is now 1, even though there are no remaining objects that reference them.We’ve created a retain cycle that prevented the objects from getting released.

This retain cycle can result in memory leak. ARC cannot figure out the retain cycle by itself so it needs some programmer intervention to help it out. We do this by distinguishing between strong and weak references in our code.

Strong and weak references

By default the references that are created are strong references. Strong references are hard to deallocate. The count to strong reference increases as the new object is created. Weak keyword is used to create a weak reference. By using the keyword weak Swift won’t allow the object reference to be incremented automatically.

We use the weak keyword to indicate that bestFriend should be a weak reference to our Animal object.


println("Program starts")
class Animal{
var name:String
weak var bestFriend:Animal?
init(name: String)
{
self.name = name
deinit
{
println("Object with name \(name) is being released")
}
}
var lion:Animal?
var tiger:Animal?
lion = Animal(name: "Lion")
tiger = Animal(name:"Tiger")
tiger?.bestFriend = lion
lion?.bestFriend = tiger
lion = nil
tiger = nil
println("Program ending")

Output:

  • Program starting
  • Object with name Lion is being released
  • Object with name Tiger is being released
  • Program ending

The objects are not released due to the circular dependency.


Viewing all articles
Browse latest Browse all 595

Trending Articles