2017-12-20 7 views
1

Ich habe Probleme, einen Retain-Zyklus aufzuspüren. Ich denke, es hat damit zu tun, wie ich Events abonniere. Pseudo-Code ist wie folgt aus:Behält sich die Verwendung einer Funktion als Verschluss selbst?

override func viewDidLoad() { 
    func handleEvent() { 
    self.doSomething() 
    } 

    subscribe("eventName", block: handleEvent) 
} 

deinit { 
    unsubscribe("eventName") 
} 

Wird dies einen Zyklus zu Selbst/meine Viewcontroller behalten schaffen? Und wenn, wie kann ich es umgehen? Wenn ich eine Schließung benutze, könnte ich [schwaches Selbst] benutzen, aber da ich eine Funktion übergebe, gibt es überhaupt ein Äquivalent für [schwaches Selbst]?

+0

Diese Frage bezieht sich auf Schließungen, ich frage über die Verwendung von Funktionen als Schließungen. Kann nicht schwaches Selbst mit einer Funktion verwenden. –

+0

Lesen Sie Ihren Code falsch ... mein schlechtes. nur eine Sekunde – PeejWeej

+1

Wir müssen wissen, was 'subscribe' mit dem übergebenen Abschluss macht, um festzustellen, ob Sie einen Retain-Zyklus haben oder nicht. Wenn es nur aufgerufen wird, ohne es zu speichern oder in einem anderen Closure zu speichern, das dann gespeichert wird (auf "self" oder etwas, auf das "self" eine starke Referenz hat), dann gibt es keinen Retain-Zyklus. Wenn es speichert/erfasst, dann haben Sie ja einen Retain-Zyklus. Es wäre sehr hilfreich, wenn Sie Ihren Code auf einen [mcve] herunterkochen könnten. – Hamish

Antwort

2

Kurz gesagt, Ihr Code behält eine Referenz. (handleEvent-> viewDidLoad-> self), http://blog.xebia.com/function-references-in-swift-and-retain-cycles/ hat einige allgemeine Strategien, um das Problem zu vermeiden. Meine Empfehlung wäre, eine Funktionsreferenz zu erstellen, anstatt eine Funktion erklärt:

let eventHandler:() ->() = { [weak self] in 
    self?.doSomething() 
} 
subscribe("eventName", block: eventHandler) 
+1

Das ist im Wesentlichen, was ich sagen wollte. Die Antwort auf die Syntaxfrage des OP lautet, dass anonyme Funktionen (einschließlich der als var-Wert zugewiesenen Funktion) die Syntax der Capture-Liste erlauben, und die benannte Funktionsdeklaration nicht. Aber ob die Situation des OP tatsächlich einen Rückhaltezyklus verursachen würde, ist unmöglich zu sagen; Das OP hat keine ausreichenden Informationen zur Verfügung gestellt. Es hängt davon ab, was "subscribe" tut und was das Schicksal seines "Block" -Parameters ist (wie Hamish zu Recht betont hat) - und das OP hat diese Information verborgen. – matt

+0

@matt es ist klar, dass es Event-Handling ist und muss in Deinit abmelden infers das Ereignis könnte/sollte feuern, nachdem die Instanz weg ist. Das Speichern einer Funktionsreferenz würde verhindern, dass dies jemals geschieht. – PeejWeej

2

Wenn Sie eine Eigenschaft oder eine Methode aus dem Innern Ihrer Klasse verweisen sie einen Zyklus beibehalten schaffen werden.

class SomeClass { 
    val a: (block: (() ->()) ->()) = ... 

    func run() { 
    func b() { 
     print("Hello, World!") 
    } 

    func c() { 
     self.someMethod() 
    } 

    func d() { [weak self] 
     self?.someMethod() 
    } 

    a(block: b) // no retain cycle 
    a(block: c) // retain cycle 
    a(block: d) // no retain cycle 
    } 

    func someMethod() { 
    print("Hello, World!") 
    } 
} 
Verwandte Themen