Intro to iOS Development
  • Welcome
    • ☀️Introduction
    • 🐣Getting Started
    • 🐦Course Staff
  • Logistics
    • 📜Syllabus
    • 🗓️Schedule
    • 🖊️Grading
    • 🙋‍♂️Office Hours
    • Ed Discussion
  • Assignments
    • 🍼A1: Swift Basics
    • 🧑A2: Profile
    • 💬A3: ChatDev
    • 👨‍🍳A4: ChefOS
    • 👨‍🍳A4: ChefOS - SwiftUI
    • 📱Hack Challenge
      • 🏆FA23 Winners
  • Lectures
    • 1️⃣Logistics + Swift Basics
    • 2️⃣UIKit + AutoLayout
  • 3️⃣MVC + Navigation + Delegation
  • 4️⃣UITableView
  • 5️⃣UICollectionView
  • 6️⃣Networking I
  • 7️⃣Networking II
  • 8️⃣SwiftUI I
  • 9️⃣SwiftUI II
  • 🔟Persistence + SnapKit
  • 🔔(11) Notifications
  • 🌎(12) Deployment and MapKit
  • Chapters
    • 🖐️Introduction
    • ☁️Git + GitHub
      • 1️⃣Git Installation
      • 2️⃣Git Basics
      • ➕Git+
    • 🐣Swift Basics
      • 1️⃣Variables and Constants
      • 2️⃣Data Types
      • 3️⃣Operators
      • 4️⃣Data Structures
      • 5️⃣Conditionals
      • 6️⃣Loops
      • 7️⃣Functions
      • 8️⃣Closures
      • 9️⃣Optionals
    • 🧰UIKit + AutoLayout
      • 1️⃣Classes
      • 2️⃣UIKit
      • 3️⃣AutoLayout
    • 📺MVC + Navigation + Delegation
      • 1️⃣MVC
      • 2️⃣Navigation
      • 3️⃣Delegation
    • 🏓UITableView
      • 1️⃣What is a UITableView?
      • 2️⃣UITableView Setup
    • 📚UICollectionView
      • 1️⃣What is a UICollectionView?
      • 2️⃣UICollectionView Setup
    • 🌐Networking I
      • 1️⃣HTTP Requests
      • 2️⃣Callbacks
      • 3️⃣Codable
    • 🌍Networking II
      • 1️⃣Alamofire
      • 2️⃣GET Requests
      • 3️⃣POST Requests
      • 4️⃣URLSession
    • 💾Persistence + SnapKit
      • 1️⃣Persistence
      • 2️⃣SnapKit
    • 🕊️SwiftUI
      • 1️⃣Introduction to SwiftUI
      • 2️⃣Getting Started with SwiftUI
      • 3️⃣Views + Modifiers
      • 4️⃣Layouts
      • 5️⃣Navigation
      • 6️⃣Property Wrappers
    • 🎛️Widgets
      • 1️⃣Introduction to Widgets
      • 2️⃣Setting Up Widgets
      • 3️⃣Building Widgets
      • 4️⃣Configuring Widgets
    • 🧱Project Foundation
    • ✅Testing
      • 1️⃣Unit Testing
    • 👣Debugging
      • 1️⃣OSLog
      • 2️⃣Crashlytics
      • 3️⃣Analytics
    • ☁️CI/CD
      • 1️⃣Xcode Cloud
      • 2️⃣AppStore Shipping
  • Guides
    • 🔨Xcode Project Setup
    • 🎨Figma
    • 📬Postman
    • 🥥CocoaPods
    • 🧰UIKit Handbook
    • 📑Tab Views
      • UITabBarController
      • TabView
  • Work in progress
    • 🧵Concurrency
    • 2️⃣UI Testing
    • 🕐Reactive Programming
    • 🧠Memory Management
      • 🔁ARC
    • 📦Storage
    • 📣Notifications
  • Archived
    • SP24
      • Logistics
        • 📜Syllabus
        • 🗓️Schedule
        • 🖊️Grading
        • 🙋‍♂️Office Hours
      • Assignments
        • 🍼A1: Swift Basics
        • 🧑A2: Profile
        • 💬A3: ChatDev
        • 👨‍🍳A4: ChefOS
        • 📱Hack Challenge
          • 🏆FA23 Winners
      • Lecture
        • 0️⃣Course Intro + Logistics + Git Setup
        • 1️⃣Swift Basics
        • 2️⃣UIKit + AutoLayout
        • 3️⃣MVC + Navigation + Delegation
        • 4️⃣UITableView
        • 5️⃣UICollectionView
        • 6️⃣Networking I
        • 7️⃣Networking II
        • 8️⃣Persistence + SnapKit
        • 🔟SwiftUI
        • 🔢TabViews
    • FA23
      • Logistics
        • 🐣Getting Started
        • 🐦Course Staff
        • 📜Syllabus
        • 🗓️Schedule
        • 🖊️Grading
        • 🙋‍♂️Office Hours
      • Assignments
        • 🍼A1: Swift Basics
        • 🧑A2: Profile
        • 💬A3: ChatDev
        • 👨‍🍳A4: ChefOS
        • 📱Hack Challenge
          • 🏆FA23 Winners
      • Lectures
        • 0️⃣Course Intro + Logistics
        • 1️⃣Swift Basics
        • 2️⃣UIKit + AutoLayout
        • 3️⃣MVC + Navigation + Delegation
        • 4️⃣UITableView
        • 5️⃣UICollectionView
        • 6️⃣Networking I
        • 7️⃣Networking II
        • 8️⃣Persistence + SnapKit
        • 🎛️Widgets
          • 👼Introduction to Widgets
          • ⚒️Setting Up Widgets
          • 🧱Building Widgets
          • 👨‍💻Configuring Widgets
        • 🔟SwiftUI
    • SP23
      • Logistics
        • Lecture Schedule
        • Syllabus
        • Grading
        • SP23 Office Hours
      • Chapters
        • 1. Intro to Swift & Xcode
          • Lecture Handout
          • Lecture Demo
          • 🍼Project: Swift Basics
        • 2. UIKit and AutoLayout
          • Lecture Handout
          • Lecture Demo
          • 🛒Project: UIKit + AutoLayout
        • 3. Navigation, MVC, and Delegation
          • Lecture Handout
          • Lecture Demo
          • Project: Navigation + Delegation
        • 4. UITableView
          • Lecture Handout
          • Lecture Demo
          • Project: UITableView
        • 5. UICollectionView
          • Lecture Handout
          • Lecture Demo
          • Project: UICollectionView
        • 6. Networking I
          • Lecture Handout
          • Lecture Demo
          • Project: Persistence
        • 7. Networking II
          • Lecture Handout
          • Lecture Demo
            • Message Board
          • Project: Networking II
        • 8. Swift UI
        • 9. CocoaPods
          • 🍫Lecture Handout
          • 🧑‍🍳Lecture Demo
      • Cheat Sheets
        • Setting Up a New Xcode Project
        • Submitting Your Projects
        • Setting Up CocoaPods
    • 2022
      • SwiftUI
    • 2021
      • Adding Flare
      • Project: UIView Animations (Optional - Extra Credit)
      • UIView Animations
      • Xcode Tips and Tricks
    • 2019
      • Firebase
      • Persistence: UserDefaults
  • Swift Guide (ARCHIVED)
    • About this Textbook
    • Documentation
    • Constants and Variables
      • Variable Properties
      • Lazy and Static Variables
    • Functions
    • Ranges
    • Arrays
      • Basic Array Operations
      • Iteration and Enumeration
      • Advanced Array Operations
    • Tuples
    • Conditions and While Loops
    • For Loops
    • Enums and Switches
      • Enums with Associated Values
      • Indirect Enums
    • Classes and Structs
    • Optionals
    • Dictionaries
      • Dictionary Implementation
    • Closures
    • Constraints
    • Generics
    • Protocols
      • Protocols With Associated Types
    • Casting
    • Errors
    • Networking
      • Result
    • Inout
Powered by GitBook
On this page
  • What is ARC?
  • Retain Cycles
  • Detecting Memory Leaks
  • Weak vs Unowned References

Was this helpful?

Export as PDF
  1. Work in progress
  2. Memory Management

ARC

Fall 2023 | Vin Bui

Have you ever wondered why we had to label our delegate variables as weak? Why do we use weak self inside of a closure? We do this to prevent memory leaks!

What is ARC?

ARC, which stands for Automatic Reference Counting, is Swift’s way of tracking and managing your app’s memory usage. Every time you create a new instance of a class, ARC allocates a chunk of memory to store the class’ information. This includes any stored properties and functions associated with that class instance.

When we no longer need that instance, ARC automatically deallocates memory used up by that instance. For example, when a view controller is displayed on screen, memory is allocated for that instance. When we dismiss that view controller, we want the stored memory to be deallocated.

How does ARC know when to deallocate memory? It uses reference counting to keep track of the number of references to that instance. If there is at least one active reference, then that instance will not be deallocated.

For example, a Person can own three devices: a Laptop, a Phone, and a Watch. Think of each device as a separate class. These three devices have a strong reference pointing to the Person. So in total, there are 4 strong references pointing to this Person instance (including itself). If we were to try to deinitialize this Person (by setting it to nil), then that instance will not be deallocated since there are 3 other strong references.

Retain Cycles

A retain cycle is a condition where two objects (instances) keep a strong reference to each other and are retained, unable to be deinitialized. A strong reference is essentially a normal reference that protects the referred object from being deallocated by increasing it’s retain count by 1.

For example, consider the following two classes. A Person has a dog property and a Dog has an owner property.

class Person {
    var name: String
    var dog: Dog?

    init(name: String, dog: Dog) {
        self.name = name
	self.dog = dog
        print("\(name) is being initialized")
    }

    deinit {
        print("\(name) is being deinitialized")
    }
}

class Dog {
    var name: String
    var owner: Person?

    init(name: String, owner: Person) {
        self.name = name
	self.owner = owner
        print("\(name) is being initialized")
    }

    deinit {
        print("\(name) is being deinitialized")
    }
}

By default, when we initialize these properties, a strong reference is retained. If we try to run the code below, the print statement inside of the initializer will be executed.

let vin = Person(name: "Vin", dog: nil)
let chubby = Dog(name: "Chubby", owner: nil)
vin.dog = chubby
chubby.owner = vin

Now, what happens if we set these properties to nil?

vin.dog = nil
chubby.owner = nil

If we try to execute the above code, we will notice that the print statements inside of the deinit function will not be executed, indicating that there is still at least one strong reference to that instance.

How do we prevent this retain cycle? By making one of the properties a weak reference. A weak reference is a pointer to the object that does not protect the referred object from being deallocated. This is possible because the retain count due to a weak reference does not increment by one.

class Person {
    var name: String
    var dog: Dog?

    init(name: String, dog: Dog) {
        self.name = name
	self.dog = dog
        print("\(name) is being initialized")
    }

    deinit {
        print("\(name) is being deinitialized")
    }
}

class Dog {
    var name: String
    weak var owner: Person? // Make this a weak variable

    init(name: String, owner: Person) {
        self.name = name
	self.owner = owner
        print("\(name) is being initialized")
    }

    deinit {
        print("\(name) is being deinitialized")
    }
}

If we try to set the properties to nil again, the print statements inside of the deinit function will now be executed.

Detecting Memory Leaks

What is the problem with retain cycles? If our view controllers are not being deallocated when they should, all of the storage occupied by the view controller’s data will stay put. Imagine having a view controller with a bunch of images. As we all know, images can take up a lot of storage. If the view controller is not deallocated when we dismiss it, the storage taken up by those images will remain. Every time we present that view controller, additional memory will be allocated, increasing the memory usage significantly. This is known as a memory leak!

You can check our app’s memory usage by clicking on the Debug Navigator (3rd icon from the right) in the project navigator, then clicking on Memory.

For a more advanced usage, we can view the memory graph by clicking on this icon:

Weak vs Unowned References

Weak and unowned references are very similar but not the same. They both do not increase the retain count by 1, but unowned references do not have to be an optional. When do we use which? According to Apple,

“Use a weak reference whenever it is valid for that reference to become nil at some point during its lifetime. Conversely, use an unowned reference when you know that the reference will never be nil once it has been set during initialization.”

PreviousMemory ManagementNextStorage

Last updated 1 year ago

Was this helpful?

On the left hand side, we can select the view and see all of the references to that view. Another powerful tool we can use is Instruments. If you want to learn more, is very informational.

If you would like to learn more, explains this concept very well.

🧠
🔁
this video
this blog post