Funkenstrahlen Podcasting, Netzpolitik, App-Entwicklung

Swift - Delegate Referenzen immer weak definieren

Heute habe ich wieder ein wenig mehr über Swift gelernt: Delegate Referenzen sollten immer als weak definiert sein!

Warum? Ich fange besser mal ganz vorne an: Swift arbeitet mit ARC (Automated Reference Counting), um Objekte aus dem Speicher zu löschen, die nicht mehr gebraucht werden. Das Prinzip davon ist recht einfach erklärt: Für jedes Objekt wird eine Strichliste geführt, wie viele Referenzen noch auf das Objekt existieren. Gibt es keine Referenz mehr, wird das Objekt aus dem Speicher entfernt - ganz automatisch.

Das macht das Leben für mich als Entwickler sehr viel einfacher, da ich micht nicht mehr selbst darum kümmern muss.

Ganz verdrängen sollte man das Thema aber nicht, denn auch mit ARC kann man sich im Speichermanagement verheddern! Was hier passieren kann, sind zyklische Referenzen: Objekt A hält eine Referenz auf Objekt B und umgekehrt. So kann ARC beide Objekte nie aus dem Speicher entfernen, da immer eine Referenz noch besteht.

Swift bietet dafür die Möglichkeit Referenzen als weak zu definieren. Das bedeutet, dass diese Referenz nicht dazu führt, dass in der ARC Strichliste der Referenzcounter hochgezählt wird.

Das Thema wird vor allem relevant, wenn man mit dem Delegate Pattern arbeitet. Hier entstehen fast immer zyklische Referenzen. Daher sollte man die delegate Variable immer weak definieren.

Hier ein kleines Beispiel:

/* 
protocol has to derive from class,
otherwise the reference can not be defined as weak
*/
protocol DogDelegate: class {
  func prepareFood()
}

class Dog {
  // define delegate as weak, will always be Optional
  weak var delegate: DogDelegate?

  func eat() {
    delegate?.prepareFood()
    print("nom nom...")
  }
}
class Home: DogDelegate {
  let rex = Dog()

  init() {
    rex.delegate = self
  }

  func prepareFood() {
    print("preparing some nice dog food.")
  }
}