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.
Memory implications of captures in 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.
value strongly by default.var value = 10 let closure = { print(value) } closure()
[weak self] avoids a strong reference cycle between the closure and the class instance.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.class Counter { var count = 0 } let counter = Counter() let closure = { [unowned counter] in print(counter.count) } closure()
This program shows how capturing person weakly in the closure allows person to be deinitialized after testClosure() ends.
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()
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.
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.