0
0
Swiftprogramming~7 mins

Memory implications of captures in Swift

Choose your learning style9 modes available
Introduction

When you use closures in Swift, they can keep references to variables outside them. This can affect how memory is used and when things get cleaned up.

You write a closure that uses variables from outside its own code block.
You want to understand why some objects stay in memory longer than expected.
You need to avoid memory leaks caused by closures holding strong references.
You want to manage memory efficiently in apps with many closures.
You are debugging retain cycles involving closures and class instances.
Syntax
Swift
let closure = { [captureList] in
    // code using captured variables
}

The captureList lets you control how variables are captured (strongly, weakly, or unowned).

Without a capture list, variables are captured strongly by default, which can cause retain cycles.

Examples
This closure captures value strongly by default.
Swift
var value = 10
let closure = { print(value) }
closure()
Using [weak self] avoids a strong reference cycle between the closure and the class instance.
Swift
class MyClass {
    var number = 5
    lazy var closure: () -> Void = { [weak self] in
        print(self?.number ?? 0)
    }
}

let obj = MyClass()
obj.closure()
[unowned] captures without increasing reference count but assumes the variable will exist when used.
Swift
class Counter {
    var count = 0
}

let counter = Counter()
let closure = { [unowned counter] in
    print(counter.count)
}
closure()
Sample Program

This program shows how capturing person weakly in the closure allows person to be deinitialized after testClosure() ends.

Swift
class Person {
    let name: String
    init(name: String) {
        self.name = name
        print("Person \(name) created")
    }
    deinit {
        print("Person \(name) is being deinitialized")
    }
}

func testClosure() {
    let person = Person(name: "Alex")
    let closure = { [weak person] in
        if let p = person {
            print("Hello, \(p.name)!")
        } else {
            print("Person no longer exists")
        }
    }
    closure()
}

testClosure()
OutputSuccess
Important Notes

Strong captures keep objects alive, which can cause memory leaks if not handled carefully.

Use [weak] or [unowned] capture lists to avoid retain cycles.

Weak captures make the captured variable optional inside the closure.

Summary

Closures capture variables and can affect memory by keeping objects alive.

Use capture lists to control how variables are captured and avoid memory leaks.

Understanding capture behavior helps write safer and more efficient Swift code.