Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
iOS Programming Cookbook

You're reading from   iOS Programming Cookbook Over 50 exciting and powerful recipes to help you unearth the promise of iOS programming

Arrow left icon
Product type Paperback
Published in Mar 2017
Publisher Packt
ISBN-13 9781786460981
Length 520 pages
Edition 1st Edition
Languages
Tools
Arrow right icon
Toc

Table of Contents (16) Chapters Close

Preface 1. Swift Programming Language FREE CHAPTER 2. The Essentials 3. Integrating with Messages App 4. Working with Interface Builder 5. Working with UITableView 6. Animations and Graphics 7. Multimedia 8. Concurrency 9. Location Services 10. Security and Encryption 11. Networking 12. Persisting Data with Core Data 13. Notifications 14. App Search 15. Optimizing Performance

Working with memory management and ARC

If you are coming from the old school where MRC (Manual Reference Counting) was being used for memory management, you definitely know how much headache developers suffer to manage memory in iOS. With iOS 5, Apple introduced ARC (Automatic Reference Counting), and life became easier in terms of memory management. Though ARC manages your memory automatically, some mistakes may ruin your memory with no mercy if you didn't understand the concept of memory management.

Getting ready

Before checking how to manage memory and avoid some common mistakes, I would like to highlight some notes:

  • Assigning a class instance to variable, constant, or properties will create a strong reference to this instance. The instance will be kept in memory as long as you use it.
  • Setting the reference to nil will reduce its reference counting by one (once it reaches zero, it will be deallocated from memory). When your class deallocated from memory, all class instance properties will be set to nil as well.

How to do it...

  1. Create two classes, Person and Dog, with a relation between them, as shown in the following code snippet (this code snippet has a memory issue called reference cycle):
      class Dog{
        var name: String
        var owner: Person!
        init(name: String){
          self.name = name
        }
      }
      class Person{
        var name: String
        var id: Int
        var dogs = [Dog]()
        init(name: String, id: Int){
          self.name = name
          self.id = id
        }
      }
      let john = Person(name: "John", id: 1)
      let rex = Dog(name: "Rex")
      let rocky = Dog(name: "Rocky")
      john.dogs += [rex, rocky] // append dogs
      rex.owner = john
      rocky.owner = john
  1. Update the reference type of owner property in the Dog class to break this cycle:
      class Dog{
        var name: String
        weak var owner: Person!
        init(name: String){
        self.name = name
      }
    }

How it works...

We have started our example by creating two classes, Person and Dog. The Person class has one-to-many relation to the Dog class via the property array dogs. The Dog class has one-to-one relation to class Person via the property owner. Everything looks good, and it works fine if you tested, but unfortunately we did a terrible mistake. We have a retain cycle problem here, which means we have two objects in memory; each one has a strong reference to the other. This leads to a cycle that prevents both of them from being deallocated from memory.

This problem is a common problem in iOS, and not all developers note it while coding. We call it as parent-child relation. Parent (in our case, it's the Person class) should always have a strong reference to child (the Dog class); child should always have a weak reference to the parent. Child doesn't need to have strong reference to parent, as child should never exit when parent is deallocated from memory.

To solve such a problem, you have to break the cycle by marking one of these references as weak. In step 2, we see how we solved the problem by marking the property owner as weak.

There's more...

The reference cycle problem can happen in situations other than relations between classes. When you use closure, there is a case where you may face a retain cycle. It happens when you assign a closure to a property in class instance and then this closure captures the instance. Let's consider the following example:

class HTMLElement { 
 
let name: String 
let text: String? 
 
lazy var asHTML: () -> String = { 
if let text = self.text { 
return "<\(self.name)>\(text)</\(self.name)>" 
        } else { 
return "<\(self.name) />" 
        } 
    } 
 
init(name: String, text: String? = nil) { 
        self.name = name 
self.text = text 
    } 
} 
 
let heading = HTMLElement(name: "h1", text: "h1 title") 
print(heading.asHTML()) // <h1>h1 title</h1> 

We have the HTMLElement class, which has closure property asHTML. Then, we created an instance of that class which is heading, and then we called the closure to return HTML text. The code works fine, but as we said, it has a reference cycle. The instance set closure to one of its property, and the closure captures the instance (happens when we call self.name and self.text inside the closure). The closure in that case will retain self (have a strong reference to the heading instance), and at the same time, heading already has a strong reference to its property asHTML. To solve reference cycle made with closure, add the following line of code as first line in closure:

[unownedself] in 

So, the class will look like this:

class HTMLElement { 
 
let name: String 
let text: String? 
 
lazy var asHTML: () -> String = { 
 
        [unownedself] in 
 
if let text = self.text { 
return "<\(self.name)>\(text)</\(self.name)>" 
        } else { 
return "<\(self.name) />" 
        } 
    } 
 
init(name: String, text: String? = nil) { 
        self.name = name 
self.text = text 
    } 
} 

The unowned keyword informs the closure to use a weak reference to self instead of the strong default reference. In that case, we break the cycle and everything goes fine.

You have been reading a chapter from
iOS Programming Cookbook
Published in: Mar 2017
Publisher: Packt
ISBN-13: 9781786460981
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime
Banner background image