2016-10-21 3 views
1

Ich habe einen View-Controller, wo ich Timer.scheduledTimer(withTimeInterval:repeats:block) aufrufen möchte, indem ich eine Funktion als Blockparameter übergebe, anstatt einen Block im laufenden Betrieb zu erstellen. Ich habe diese Ansicht-Controller:Wie übergibt man eine Funktion als Parameter, um Retain-Zyklen zu vermeiden?

class ViewController: UIViewController { 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     Timer.scheduledTimer(withTimeInterval: 5, 
          repeats: true, 
          block: onTimer)  
    } 

    deinit { 
     print("deinit \(self)") 
    } 

    func onTimer(_ timer: Timer) { 
     print("Timer did fire") 
    } 
} 

Der Aufruf der View-Controller wird beibehalten, so dass die Steuerung wird nie freigegeben.

Ich weiß, ich kann es, wie ich mit durch Ersetzen des rufenden funktioniert:

Timer.scheduledTimer(withTimeInterval: 5, 
         repeats: true) { [weak self] timer in 

          self?.onTimer(timer) 
    } 

Aber ich möchte wissen, ob es einen Weg gibt, die onTimer Verfahren direkt und vermeiden Sie den behalten Zyklus senden .

Danke.

+0

Ihre Tags zeigen bereits an, dass Sie Swift verwenden. Es besteht keine Notwendigkeit, es als Teil des Titels zu haben. –

+1

Sie haben es selbst gesagt, wenn Sie keinen starken Referenzzyklus wünschen, verwenden Sie eine schwache Referenz. Ihr Zeitgeber verweist auf Ihre Instanzmethode und die Instanz verweist auf den Zeitgeber. Die einzige Möglichkeit, dies zu umgehen, besteht darin, entweder die Instanzmethode oder den Zeitgeber zu verschieben, sodass sie nicht in derselben Instanz liegen. Aber zu welchem ​​Effekt? – Alexander

+0

Wenn Ihr 'onTimer' keine Instanzdaten benötigt, können Sie es statisch machen, wodurch der Zyklus unterbrochen wird. – Alexander

Antwort

2

Sie sollten die invalidate() Methode aufrufen:

Diese Methode ist die einzige Möglichkeit, einen Timer von einem Runloop Objekt zu entfernen. Das RunLoop-Objekt entfernt seine starke Referenz auf den Timer, entweder , kurz bevor die invalidate() -Methode zurückgegeben wird oder zu einem späteren Zeitpunkt.

Wenn es mit Ziel- und Benutzer-Info-Objekten konfiguriert wurde, entfernt der Empfänger seine starken Referenzen auf diese Objekte ebenfalls.

Irgendwo im Code, sollten Sie implementieren:

timer.invalidate() 

Hope this geholfen.

Verwandte Themen