2014-09-20 25 views
71

Wie kann ich jede Minute eine Funktion ausführen? In JavaScript kann ich etwas tun wie setInterval, gibt es etwas ähnliches in Swift?In Swift alle x Minuten etwas tun

gewünschte Ausgabe:

Hallo Welt einmal eine Minute ...

+0

Aktualisiert für Swift 2: [Swift Timer] (http://www.ios-blog.co.uk/tutorials/swift/swift-nstimer-tutorial-lets-create-a-counter-application/) – JamesG

+0

Wie kann ich das in Ziel C tun? –

Antwort

120
var helloWorldTimer = NSTimer.scheduledTimerWithTimeInterval(60.0, target: self, selector: Selector("sayHello"), userInfo: nil, repeats: true) 

func sayHello() 
{ 
    NSLog("hello World") 
} 

Denken Sie daran, Foundation zu importieren.

Swift 3:

var helloWorldTimer = Timer.scheduledTimer(timeInterval: 60.0, target: self, selector: #selector(ViewController.sayHello), userInfo: nil, repeats: true) 

func sayHello() 
{ 
    NSLog("hello World") 
} 
+1

aber was ist, wenn Sie zwischen Ansichten wechseln möchten? Der Code wird richtig aufhören? – Cing

+5

@Cing hängt davon ab, worauf es sich bezieht. – Antzi

+1

Vergessen Sie nicht, dass 'NSTimer' sein Ziel beibehält. Wenn also' helloWorldTimer' eine Eigenschaft auf 'self' ist, haben Sie bei diesem Setup selbst einen Retain-Zyklus, wobei' self' 'helloWorldTimer' und' halloWorldTimer 'beibehält 'behält" sich selbst ". –

10

Sie NSTimer

var timer = NSTimer.scheduledTimerWithTimeInterval(60, target: self, selector: Selector("function"), userInfo: nil, repeats: true) 

In Selektor() verwenden Sie in Ihrer Funktionsnamen setzen

+0

Wie können Sie es in swift 3 tun? – bibscy

103

In Swift 3 können Sie eine Timer erstellen. Und wenn Targeting iOS Version 10 und höher, können Sie die blockbasierte Wiedergabe verwenden, die die möglichen starken Referenzzyklen vereinfacht, z.B .:

weak var 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) { [weak self] _ in 
     // do something here 
    } 
} 

func stopTimer() { 
    timer?.invalidate() 
} 

// if appropriate, make sure to stop your timer in `deinit` 

deinit { 
    stopTimer() 
} 

In Swift 2 erstellen Sie eine NSTimer. Und wenn Sie mit Swift 2, können Sie auch seine mit iOS Version vor 10.0, in dem Fall, dass Sie die älteren target/selector Muster verwenden:

weak var timer: NSTimer? 

func startTimer() { 
    timer?.invalidate() // just in case you had existing `NSTimer`, `invalidate` it before we lose our reference to it 
    timer = NSTimer.scheduledTimerWithTimeInterval(60.0, target: self, selector: #selector(handleTimer(_:)), userInfo: nil, repeats: true) 
} 

func handleTimer(timer: NSTimer) { 
    // do something here 
} 

func stopTimer() { 
    timer?.invalidate() 
} 

// because this old target/selector approach will keep a strong reference 
// to the `target`, if you want the timer to stop when the view controller 
// is dismissed, you can't stop the timer in `deinit`, but rather have to 
// detect the dismissing of the view controller using other mechanisms. Commonly, 
// we used to detect the view disappearing, like below: 

override func viewDidDisappear(animated: Bool) { 
    super.viewDidDisappear(animated) 
    stopTimer() 
} 

Während NSTimer im Allgemeinen am besten ist, Der Vollständigkeit halber sei angemerkt, dass Sie auch den Dispatch-Timer verwenden können, der nützlich ist, um Timer auf Hintergrund-Threads zu terminieren. Mit Sende-Timern, da sie blockbasiert sind, vermeidet es einige der starken Referenzzyklus-Herausforderungen mit dem alten target/selector Muster von NSTimer, solange Sie weak Referenzen verwenden.

Also, in Swift 3:

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!.scheduleRepeating(deadline: .now(), interval: .seconds(60)) 
    timer!.setEventHandler { [weak self] in 
     // do whatever you want here 
    } 
    timer!.resume() 
} 

func stopTimer() { 
    timer?.cancel() 
    timer = nil 
} 

deinit { 
    self.stopTimer() 
} 

In Swift 2:

var timer: dispatch_source_t? 

func startTimer() { 
    let queue = dispatch_queue_create("com.domain.app.timer", nil) // again, you can use `dispatch_get_main_queue()` if you want to use the main queue 
    timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue) 
    dispatch_source_set_timer(timer!, DISPATCH_TIME_NOW, 60 * NSEC_PER_SEC, 1 * NSEC_PER_SEC) // every 60 seconds, with leeway of 1 second 
    dispatch_source_set_event_handler(timer!) { [weak self] in 
     // do whatever you want here 
    } 
    dispatch_resume(timer!) 
} 

func stopTimer() { 
    if let timer = timer { 
     dispatch_source_cancel(timer) 
     self.timer = nil 
    } 
} 

deinit { 
    self.stopTimer() 
} 

Weitere Informationen finden Sie in der die Erstellen eines Timer Abschnitt Versand Quelle Beispiele im Dispatch Sources Abschnitt der Concurrency Programming Guide.

+0

Wie würden Sie bei diesem Ansatz für einen Nur-Ausführen-Einmal-Timer gehen? –

+0

@JuanPabloBoero - Ich würde diesen Ansatz nicht für eine einmalige Situation verwenden. Sie würden 'dispatch_after' verwenden. Oder ein sich nicht wiederholender 'NSTimer'. – Rob

+0

@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. Aber das Problem, mit dem ich konfrontiert bin, ist, dass meine Zählervariable jede Sekunde aktualisiert wird, aber der Bildschirm zeigt nicht den neuesten Zählerwert in meinem UILabel. – Rao

5

In swift 3.0 GCD Refactoring wurde:

let timer : DispatchSourceTimer = DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue.main) 

timer.scheduleRepeating(deadline: .now(), interval: .seconds(60)) 
timer.setEventHandler 
{ 
    NSLog("Hello World") 
} 
timer.resume() 

Diese für besonders nützlich ist, wenn Sie auf eine bestimmte Warteschlange versenden müssen. Auch wenn Sie dies für die Aktualisierung der Benutzeroberfläche planen, empfehle ich, in CADisplayLink zu suchen, da es mit der GPU-Aktualisierungsrate synchronisiert ist.

11

Hier ist ein Update auf die NSTimer Antwort, für Swift 3 (in der NSTimer-Timer umbenannt wurde), um eine Schließung statt einer benannten Funktion:

var timer = Timer.scheduledTimer(withTimeInterval: 60, repeats: true) { 
    (_) in 
    print("Hello world") 
} 
+5

das ist nur für iOS 10. – Glenn

+0

posten Sie bitte keine ios 10+ Lösungen –

0

Wenn Sie erlauben eine Zeitdrift hier ist eine einfache Lösung, einige Codes jede Minute ausführen:

private func executeRepeatedly() { 
    // put your code here 

    DispatchQueue.main.asyncAfter(deadline: .now() + 60.0) { [weak self] in 
     self?.executeRepeatedly() 
    } 
} 

Nur executeRepeatedly() einmal laufen und es wird jede Minute ausgeführt werden. 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.