# Automatic Reference Counting — Swift

Source: https://www.skillbyai.com/en/swift/m-arc

> Explain ARC, strong, weak and unowned references, and fix retain cycles.

## How Swift frees class instances

Swift manages memory for class instances with **Automatic Reference Counting (ARC)**. Each instance keeps a count of **strong references**; when the count reaches zero, the instance is deallocated immediately and its `deinit` runs. There is no garbage collector pausing your app, and value types (structs, enums) are not reference-counted in the same way. ARC's weakness is **retain cycles**: two objects holding strong references to each other (a view controller and a closure that captures it, or a parent and child that point to each other) never reach zero and leak. Break cycles with **`weak`** references, which do not increase the count and become `nil` automatically when the object is freed (so they are optional vars), or **`unowned`** references, which also do not increase the count but assume the object outlives the reference and crash if it does not. Typical rule: delegates are `weak`, closures stored by the object they capture use `[weak self]`, and child-to-parent links are `weak` or `unowned`. Xcode's **Memory Graph Debugger** and Instruments' **Leaks** tool find cycles.

## A retain cycle

Two objects holding strong references to each other are never freed; a weak link breaks the cycle.

![Two circles connected by two solid arrows forming a loop, and below them the same circles with one arrow drawn dashed.](assets/figures/swift/section-6-map.svg) — Figure 6.1 — A strong reference cycle and the weak reference that breaks it.

## A delegate cycle and the weak fix

The weak delegate lets both objects be freed.

```swift
protocol DownloaderDelegate: AnyObject {          // AnyObject: class-only, so it can be weak
    func downloadFinished(_ data: Data)
}

final class Downloader {
    weak var delegate: DownloaderDelegate?        // weak: does not keep the screen alive
    var onProgress: ((Double) -> Void)?

    func start() { /* ... */ }
}

final class ProductScreen: DownloaderDelegate {
    let downloader = Downloader()
    var progressText = ""

    init() {
        downloader.delegate = self
        downloader.onProgress = { [weak self] value in   // avoid screen -> downloader -> closure -> screen
            self?.progressText = "\(Int(value * 100))%"
        }
    }

    func downloadFinished(_ data: Data) { /* update UI */ }

    deinit { print("ProductScreen freed") }        // prints when the screen goes away
}
```

## Missing deinit output is a clue

Add a temporary `deinit { print(...) }` to a screen or controller and close it. If nothing prints, something still holds a strong reference, very often a closure capturing `self`.

**Quiz:** What happens to a weak reference when the object it refers to is deallocated?

- [ ] The app crashes
- [ ] It keeps the object alive
- [x] It automatically becomes nil
- [ ] It points to a copy of the object

*Answer:* It automatically becomes nil. Weak references are zeroed automatically, which is why they must be optional variables.
