Swift Memory Management: Speichern der Funktion in var

Ich suche nach der besten Methode zum Speichern von Funktionen als Variable in anderen Objekten. Insbesondere möchte ich vermeiden, Zyklen beizubehalten, die bei der Erfassung von @ auftreteself in der Funktion.

Ausgehend von Objective-C und Blöcken würde ich normalerweise Folgendes tun:

__weak id _self = self;
iVar.someBlock = ^{
    [_self doSomething];
};

Natürlich dieiVar class kopiert den Block und speichert ihn. Es ist kein Aufbewahrungszyklus vorhanden, da ich capture @ hab__weak id _self.

In Swift bin ich mir etwas weniger sicher, zumal ich Klassenfunktionen / Methoden übergeben kann. Also, lassen Sie uns in der @ sagiVar Klasse, die ich habe:

class iVarClass {
    var callBack:() -> ()?
    func jumpUpAndDown(){
        //Weeeeeee!
        self.callBack?()
    }
}

Jetzt in meiner "Haupt" -Klasse habe ich eine Instanzvariable der oben genannten Klasse und das mache ich:

class mainClass {
    var iVar: iVarClass
    init(iVar:iVarClass){
        self.iVar = iVar
        iVar.callback = self.doSomething
    }
    func doSomething(){
      self.iVar.jumpUpAndDown?()
    }
}

Haben wir hier einen Retain-Zyklus? Ich denke schon, und ich denke, dass ich vielleicht das @ machen mucallback schwach:

    weak var callBack:() -> ()?

Natürlich könnte ich so etwas in der Hauptklasse machen:

    init(iVar:iVarClass){
        self.iVar = iVar
        weak var _self = self
        iVar.callback = {
            _self?.doSomething()
        }
    }

Aber es ist so schön, Klassenfunktionen als Argumente übergeben zu können! Auch wenn ich das @ machen mucallback schwach, dann denke ich, dass ich die Möglichkeit verlieren würde, ihm einen Abschluss zuzuweisen (da der Abschluss nach der Zuweisung mit nur einem schwachen Verweis aus dem Speicher freigegeben würde).

Auch beachten Sie, dass die Verantwortung für die Speicherverwaltung jetzt beim Empfänger liegt und nicht beim Zuweiser. Da der Empfänger jedoch die Quelle der Zuweisung nicht kennen kann, kann er nicht wirklich dafür verantwortlich gemacht werden. Mit anderen Worten, es muss jetzt ein impliziter Vertrag zwischen dem Empfänger und dem Zuweiser darüber bestehen, welche Art von Funktion übergeben werden soll, was fragil und nicht empfehlenswert ist. Wenn der Zuweiser verantwortlich ist, kann er Maßnahmen ergreifen, um sicherzustellen, dass es keinen Aufbewahrungszyklus gibt, aber der Empfänger kann solche Maßnahmen nicht ergreifen.

Dies lässt mich denken, dass wir @ solltnoch ni eine Klassenfunktion an ein anderes Objekt übergeben. Es ist zu gefährlich. Sie können nicht wissen, wie der Empfänger es speichern / verwenden wird.

Oder vermisse ich etwas? Löst Swift dieses Problem auf magische Weise hinter den Kulissen?

Aktualisiere

irsteins wies auf etwas hin, das ich vergessen hatte: Erfassungslisten. Anstatt also explizit @ zu deklarierweak var _self = self, Sie können es stattdessen im Closure deklarieren:

    init(iVar:iVarClass){
        self.iVar = iVar
        iVar.callback = { [weak self] in
            self?.doSomething()
        }
    }

Das ist besser, aber nicht annähernd so elegant wie das Zuweisen der Klassenfunktion.

Ich denke was ichwolle bedeutet, dass Swift eine Klassenfunktion automatisch in einen Abschluss mit einer Erfassungsliste konvertiert, sodass ich das nicht tun muss. Um fair zu sein, es ist nicht gerade schwierig, aber sicherlich viel schöner, wenn ich nur die Klassenfunktion zuweisen könnte. Hölle, auch das wäre schöner:

self.iVar.callback = weak self.doSomething

Antworten auf die Frage(2)

Ihre Antwort auf die Frage