aber was ist, wenn Sie zwischen den Ansichten wechseln möchten? Der Code wird richtig aufhören?
Cing
5
@Cing hängt davon ab, worauf sich selbst bezieht.
Antzi
1
Vergessen Sie nicht , dass NSTimeres das Ziel, so, mit dieser Einstellung behält, wenn helloWorldTimereine Eigenschaft auf selfSie sich ein Zyklus behalten haben, wo selfbehält helloWorldTimerund helloWorldTimerbehält self.
MANIAK_dobrii
@MANIAK_dobrii Können Sie auch kommentieren, wie der Aufbewahrungszyklus unterbrochen werden kann? Wenn der VC entlassen wird, der Timer jedoch nicht abgebrochen wird, ist der Zyklus noch in Takt? Sie müssen also beide den Timer abbrechen und dann die Ansicht schließen, um den Zyklus zu unterbrechen?
Dave G
1
Für Swift 4 muss die Methode, für die Sie den Selektor erhalten möchten, für Objective-C verfügbar gemacht werden. Daher muss das Attribut @objc zur Methodendeklaration hinzugefügt werden. zB `` `@objc func sayHello () {}` ``
Shamim Hossain
136
Wenn Sie auf iOS Version 10 und höher abzielen, können Sie die blockbasierte Wiedergabe von verwenden Timer, die die potenziell starken Referenzzyklen vereinfacht, z.
weakvar timer:Timer?func startTimer(){
timer?.invalidate()// just in case you had existing `Timer`, `invalidate` it before we lose our reference to it
timer =Timer.scheduledTimer(withTimeInterval:60.0, repeats:true){[weakself]_in// do something here
}}func stopTimer(){
timer?.invalidate()}// if appropriate, make sure to stop your timer in `deinit`
deinit{
stopTimer()}
Obwohl dies Timerder Vollständigkeit halber im Allgemeinen am besten ist, sollte ich beachten, dass Sie auch den Versand-Timer verwenden können, der zum Planen von Timern für Hintergrund-Threads nützlich ist. Da Dispatch-Timer blockbasiert sind, werden einige der starken Herausforderungen des Referenzzyklus mit dem alten target/ selectorMuster von vermieden Timer, solange Sie weakReferenzen verwenden.
So:
var timer:DispatchSourceTimer?func startTimer(){let queue =DispatchQueue(label:"com.domain.app.timer")// you can also use `DispatchQueue.main`, if you want
timer =DispatchSource.makeTimerSource(queue: queue)
timer!.schedule(deadline:.now(), repeating:.seconds(60))
timer!.setEventHandler {[weakself]in// do whatever you want here
}
timer!.resume()}func stopTimer(){
timer?.cancel()
timer =nil}deinit{self.stopTimer()}
Weitere Informationen finden Sie in der das Erstellen eines Timer Abschnitt Versand Quelle Beispiele in der Dispatch - Quellen Abschnitt des Concurrency Programming Guide.
Wie würden Sie bei diesem Ansatz einen Timer wählen, der nur einmal ausgeführt wird?
Juan Boero
@JuanPabloBoero - Ich würde diesen Ansatz nicht für eine einmalige Feuersituation verwenden. Du würdest benutzen dispatch_after. Oder eine sich nicht wiederholende NSTimer.
Rob
@Rob Ich habe eine Zählerbeschriftung auf dem Bildschirm, die jede Sekunde von einer Funktion aktualisiert wird, und ich verwende den obigen Code, um meinen Zähler zu erhöhen und den Beschriftungstext zu aktualisieren. Das Problem ist jedoch, dass meine Zählervariable jede Sekunde aktualisiert wird, der Bildschirm jedoch nicht den neuesten Zählerwert in meinem UILabel anzeigt.
Nagendra Rao
Rao, das Obige ist nützlich, um eine Aktion für einen Hintergrund-Thread auszuführen. Ihre UI-Updates müssen jedoch in der Hauptwarteschlange erfolgen. Planen Sie dies entweder im Hauptthread oder senden Sie die UI-Updates zumindest zurück an den Hauptthread.
Rob
1
Diese Frage gehört hier nicht in die Kommentare zu dieser Antwort. Löschen Sie Ihre Kommentare oben und stellen Sie Ihre eigene Frage. Kurz gesagt, Sie lassen die App im Allgemeinen nicht im Hintergrund laufen, sondern lassen sie nur so aussehen, wie sie war. Siehe stackoverflow.com/a/31642036/1271826 .
Rob
17
Hier ist ein Update der NSTimerAntwort für Swift 3 (in das NSTimerumbenannt wurde Timer), bei dem ein Abschluss anstelle einer benannten Funktion verwendet wird:
var timer =Timer.scheduledTimer(withTimeInterval:60, repeats:true){(_)in
print("Hello world")}
Wenn Sie eine gewisse Zeitverschiebung zulassen können , finden Sie hier eine einfache Lösung, mit der jede Minute Code ausgeführt wird:
privatefunc executeRepeatedly(){// put your code here
DispatchQueue.main.asyncAfter(deadline:.now()+60.0){[weakself]inself?.executeRepeatedly()}}
Nur executeRepeatedly()einmal ausführen und es wird jede Minute ausgeführt. Die Ausführung wird beendet, wenn das besitzende Objekt ( self) freigegeben wird. Sie können auch ein Flag verwenden, um anzuzeigen, dass die Ausführung gestoppt werden muss.
let timer :DispatchSourceTimer=DispatchSource.makeTimerSource(flags:[], queue:DispatchQueue.main)
timer.scheduleRepeating(deadline:.now(), interval:.seconds(60))
timer.setEventHandler
{NSLog("Hello World")}
timer.resume()
Dies ist besonders nützlich, wenn Sie in einer bestimmten Warteschlange versenden müssen. Wenn Sie dies für die Aktualisierung der Benutzeroberfläche verwenden möchten, sollten Sie prüfen, ob CADisplayLinkes mit der GPU-Aktualisierungsrate synchronisiert ist.
Antworten:
Denken Sie daran, Foundation zu importieren.
Swift 4:
quelle
NSTimer
es das Ziel, so, mit dieser Einstellung behält, wennhelloWorldTimer
eine Eigenschaft aufself
Sie sich ein Zyklus behalten haben, woself
behälthelloWorldTimer
undhelloWorldTimer
behältself
.Wenn Sie auf iOS Version 10 und höher abzielen, können Sie die blockbasierte Wiedergabe von verwenden
Timer
, die die potenziell starken Referenzzyklen vereinfacht, z.Obwohl dies
Timer
der Vollständigkeit halber im Allgemeinen am besten ist, sollte ich beachten, dass Sie auch den Versand-Timer verwenden können, der zum Planen von Timern für Hintergrund-Threads nützlich ist. Da Dispatch-Timer blockbasiert sind, werden einige der starken Herausforderungen des Referenzzyklus mit dem altentarget
/selector
Muster von vermiedenTimer
, solange Sieweak
Referenzen verwenden.So:
Weitere Informationen finden Sie in der das Erstellen eines Timer Abschnitt Versand Quelle Beispiele in der Dispatch - Quellen Abschnitt des Concurrency Programming Guide.
Für Swift 2 siehe vorherige Überarbeitung dieser Antwort .
quelle
dispatch_after
. Oder eine sich nicht wiederholendeNSTimer
.Hier ist ein Update der
NSTimer
Antwort für Swift 3 (in dasNSTimer
umbenannt wurdeTimer
), bei dem ein Abschluss anstelle einer benannten Funktion verwendet wird:quelle
Wenn Sie eine gewisse Zeitverschiebung zulassen können , finden Sie hier eine einfache Lösung, mit der jede Minute Code ausgeführt wird:
Nur
executeRepeatedly()
einmal ausführen und es wird jede Minute ausgeführt. Die Ausführung wird beendet, wenn das besitzende Objekt (self
) freigegeben wird. Sie können auch ein Flag verwenden, um anzuzeigen, dass die Ausführung gestoppt werden muss.quelle
Sie können verwenden
Timer
(schnell 3)In selector () geben Sie Ihren Funktionsnamen ein
quelle
Timer
...NSTimer
wurde umbenanntIn Swift 3.0 wurde die GCD überarbeitet:
Dies ist besonders nützlich, wenn Sie in einer bestimmten Warteschlange versenden müssen. Wenn Sie dies für die Aktualisierung der Benutzeroberfläche verwenden möchten, sollten Sie prüfen, ob
CADisplayLink
es mit der GPU-Aktualisierungsrate synchronisiert ist.quelle