Chapters

Hide chapters

Swift Cookbook

Live Edition · Multiplatform · Swift · Editor agnostic

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.

© 2024 Kodeco Inc.