2014-11-14 9 views
6

Ich habe versucht, eine Menge Forschung über das Verständnis von Retain-Zyklen zu tun. Ich kann jedoch nichts an meinen Beispielen finden. Ich weiß, dass, wenn ich eine Eigenschaft auf eine Schließung setze, ein Retain-Zyklus stattfindet und schwache oder nicht-kommunizierte verwenden muss. Aber ich habe 2 Beispiele, die ich gerne wissen würde, ob sie richtig gemacht wurden: Danke im Voraus, ich habe versucht zu sehen, ob sie bereits auf stackoverflow sind, aber nichts gefunden haben.Swift Retain Cycles und Closures

einfache Animationen

UIView.transitionWithView(self, duration: 5, options: .TransitionCrossDissolve, animations: { [weak self] in 
    self?.setNeedsDisplay() 
    return 
}, completion: nil) 

Animationen mit einem Array

for imageView in self.townImages { 
    UIView.transitionWithView(imageView, duration: 0.3, options: .TransitionCrossDissolve, animations: {() -> Void in 
     imageView.image = UIImage(named: self.getImages()[count++]) 
    }, completion: nil) 
} 

In beiden Beispielen self ist eine Unterklasse von UIView. Ich möchte nur wissen, dass ich es richtig mache oder ob ich imageView auch als schwache Referenz verwenden soll. Vielen Dank.

Antwort

2

Keines von diesen erstellt Haltezyklen, da der Block nicht an self angehängt ist. Darüber hinaus sind Retain-Zyklen mit garantierter Lebensdauer nicht das Schlimmste auf der Welt.

Betrachten wir einige Beispiele. (sorry, ist mein swift nicht besonders stark, so werde ich obj-c zurückzukehren.)


- (void)doSomething:(void(^)())block { 
    self.block = block; 
} 

// elsewhere 
    [self doSomething:^{ 
    self.someProperty = 5; 
    }]; 

Dies ist ein Zyklus beibehalten schafft, weil self verwiesen wird (nicht schwach) innerhalb ein Block, auf den self eine Referenz enthält.


[UIView transitionWithView:self duration:5, options:UIViewAnimationOptionTransitionCrossDissolve animations:^{ 
    [self setNeedsDisplay]; 
} completion:nil]; 

Dies schafft nicht ein Zyklus beibehalten, weil der animations Block an das System geschickt wird - Ihre UIView Unterklasse nicht halten einen Verweis auf den Block.


Exkurs: Sie sollten keine return am Ende des Verschlusses haben müssen, aber ich denke, swift lächerlich ist und versucht, „nützlich“ zu sein. Außerdem bin ich nicht sicher, dass Sie während der Animation self.setNeedsDisplay() aufrufen müssen, da es das selbst tun sollte ...

+0

Also bedeutet das, dass es nur einen Retain-Zyklus erstellt, wenn meine Klasse einen Verweis auf den Block enthält? Oder würde die 'UIView.transitionWithView'-Methode auch einen Retain-Zyklus erzeugen? Mit anderen Worten, wenn eine Klasse einen Verweis auf den Block hätte, würde es einen Retain-Zyklus erzeugen. – smitt04

+1

auch die Rückkehr im ersten Beispiel war, weil in swift, wenn nur eine Aussage in einer Schließung gemacht wurde, es automatisch diesen Wert zurückgibt, und in diesem Fall erwartete die Schließung einen Rückgabewert von Void, also verwende ich die Rückkehranweisung, um void und nicht zurückzugeben das Ergebnis von 'self? .setNeedsDisplay()' – smitt04

+1

Ja, seltsam aber wahr: in Swift brauchst du die Rückkehr in diesem Fall. Eine der Kuriositäten der verschiedenen Regeln der Sprache für die Schließung von einem Statement. (Und die aktuelle Version des Compilers wirft eine irrelevante und völlig irreführende Fehlermeldung, wenn sie auch nicht da ist ...) –