2016-04-21 14 views
0

In Swift können wir Feature, das wir nicht in ObjC hatten: Es ist möglich, eine Methode überall dort zu verwenden, wo Sie eine Schließung verwenden würden. Aber es kann dazu führen, Zyklen zu behalten. Schau dir dieses Beispiel an:Retain-Zyklus passiert, wenn Methode statt Schließung übergeben

import Foundation 

class C1 { 
    let closure: Void -> Void 
    init(closure: Void -> Void) { 
     self.closure = closure 
    } 

    deinit { 
     print("C1 deinit") 
    } 
} 

class C2 { 
    var c1: C1! 

    func initializeC1() { 
     c1 = C1(closure: f) 
    } 

    func f() {} 

    deinit { 
     print("C2 deinit") 
    } 
} 

func main() { 
    let c2 = C2() 
    c2.initializeC1() 
} 

main() 

Hier haben wir Zyklus C2 -> C1 -> f -> C2 erstellt. Wenn Sie dieses Programm ausführen, wird deinit nicht aufgerufen. Aber wenn Sie zum Beispiel f in initializeC1 zu {} ersetzen, wird es sein.

Für reguläre Verschlüsse können wir Capture-Listen verwenden, um eine starke Beibehaltung zu vermeiden, aber es sieht so aus, als ob Sie sie nicht für Methoden verwenden können. So ist die Frage: Wie können wir den Zyklus in einer solchen Situation zu brechen und ist es überhaupt möglich?

Antwort

3

Sicherlich können wir „weakify“ eine gebundene Methode, indem sie es in Schließung Einwickeln in etwa so:

import Foundation 

class C1 { 
    let closure: Void -> Void 
    init(closure: Void -> Void) { 
     self.closure = closure 
    } 

    deinit { 
     print("C1 deinit") 
    } 
} 

class C2 { 
    var c1: C1! 

    func initializeC1() { 
     // HERE we wrap a method call into a closure to break retain-cycle. 
     c1 = C1(closure: { [weak self] in 
      self?.f() 
     }) 
    } 

    func f() {} 

    deinit { 
     print("C2 deinit") 
    } 
} 

func main() { 
    let c2 = C2() 
    c2.initializeC1() 
} 

main() 
//C2 deinit 
//C1 deinit 
+0

Nizza Antwort, aber wir kamen wieder auf die Schließung Syntax zurück, die ich versuchte, zu vermeiden. Wenn es keine bessere Lösung gibt, wird die Antwort angenommen. –

+0

Ich sehe keine klare Aussage in den Dokumenten, aber es scheint, dass Methoden _strongly_ an ihre Instanzen in Swift gebunden sind und wir haben keine Möglichkeit, dieses Verhalten zu ändern. Ich sehe auch keinen Weg, um einen nützlichen Nutzen daraus zu ziehen. – werediver