ARC and Closures
Written by Team Kodeco
Closures are self-contained blocks of code that can be passed around and used in your application. They can capture and store references to any constants and variables from the context in which they are defined.
When a closure captures a reference to an object, it increases the object’s reference count. This can cause a retain cycle, where two objects have strong references to each other and neither can be deallocated by ARC.
Here is an example of a retain cycle caused by a closure:
class Wizard {
var name: String
var spell: (() -> Void)?
init(name: String) {
self.name = name
}
deinit {
print("Wizard \(name) is fading away.")
}
}
var wizard: Wizard? = Wizard(name: "Harry Potter")
wizard?.spell = { [wizard] in
print("\(wizard?.name) casts Expelliarmus!")
}
wizard = nil
// Harry is not fading away, because the spell still holds a strong reference
In this example, the spell
closure captures a strong reference to wizard
, preventing it from being deallocated.
To avoid retain cycles caused by closures, you can use the weak
or unowned
keyword when capturing references to objects.
var wizard: Wizard? = Wizard(name: "Harry Potter")
wizard?.spell = { [weak wizard] in
print("\(wizard?.name) casts Expelliarmus!")
}
wizard = nil
// Output: Wizard Harry Potter is fading away.
By using the weak
keyword when capturing the reference to the object, the closure no longer increases the object’s reference count and the object can be deallocated by ARC.