Jak Mogę używać timera (dawniej NSTimer) w języku Swift?
Próbowałem
var timer = NSTimer()
timer(timeInterval: 0.01, target: self, selector: update, userInfo: nil, repeats: false)
Ale, mam błąd mówiąc
'(timeInterval: $T1, target: ViewController, selector: () -> (), userInfo: NilType, repeats: Bool) -> $T6' is not identical to 'NSTimer'
16 answers
To zadziała:
override func viewDidLoad() {
super.viewDidLoad()
// Swift block syntax (iOS 10+)
let timer = Timer(timeInterval: 0.4, repeats: true) { _ in print("Done!") }
// Swift >=3 selector syntax
let timer = Timer.scheduledTimer(timeInterval: 0.4, target: self, selector: #selector(self.update), userInfo: nil, repeats: true)
// Swift 2.2 selector syntax
let timer = NSTimer.scheduledTimerWithTimeInterval(0.4, target: self, selector: #selector(MyClass.update), userInfo: nil, repeats: true)
// Swift <2.2 selector syntax
let timer = NSTimer.scheduledTimerWithTimeInterval(0.4, target: self, selector: "update", userInfo: nil, repeats: true)
}
// must be internal or public.
@objc func update() {
// Something cool
}
Dla Swift 4, metoda, której chcemy uzyskać selektor musi być wystawiona na Objective-C, zatem atrybut @objc
musi być dodany do deklaracji metody.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-16 17:50:08
Powtarzające się Zdarzenie
Możesz użyć timera, aby wykonać czynność wiele razy, jak pokazano w poniższym przykładzie. Timer wywołuje metodę aktualizacji etykiety co pół sekundy.
Oto kod do tego:
import UIKit
class ViewController: UIViewController {
var counter = 0
var timer = Timer()
@IBOutlet weak var label: UILabel!
// start timer
@IBAction func startTimerButtonTapped(sender: UIButton) {
timer.invalidate() // just in case this button is tapped multiple times
// start the timer
timer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(timerAction), userInfo: nil, repeats: true)
}
// stop timer
@IBAction func cancelTimerButtonTapped(sender: UIButton) {
timer.invalidate()
}
// called every time interval from the timer
func timerAction() {
counter += 1
label.text = "\(counter)"
}
}
Opóźnione Zdarzenie
Można również użyć timera do zaplanowania jednorazowego zdarzenia na jakiś czas w przyszłości. Główną różnicą od powyższego przykładu jest to, że używasz repeats: false
zamiast true
.
timer = Timer.scheduledTimer(timeInterval: 2.0, target: self, selector: #selector(delayedAction), userInfo: nil, repeats: false)
Powyższy przykład wywołuje metodę nazwane delayedAction
dwie sekundy po ustawieniu timera. Nie jest to powtarzane, ale nadal możesz wywołać timer.invalidate()
, jeśli chcesz anulować wydarzenie, zanim kiedykolwiek się ono wydarzy.
Uwagi
- Jeśli istnieje jakakolwiek szansa na wielokrotne uruchomienie wystąpienia timera, upewnij się, że najpierw unieważnisz starą instancję timera. W przeciwnym razie stracisz odniesienie do zegara i nie możesz go już zatrzymać. (zobacz to Q&A )
- nie używaj timerów, gdy nie są potrzebne. Zobacz dział Zegary z [[29]}Przewodnik efektywności energetycznej dla aplikacji na iOS.
Powiązane
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-12-05 06:31:37
Zaktualizowano do Swift 4, wykorzystując userInfo:
class TimerSample {
var timer: Timer?
func startTimer() {
timer = Timer.scheduledTimer(timeInterval: 5.0,
target: self,
selector: #selector(eventWith(timer:)),
userInfo: [ "foo" : "bar" ],
repeats: true)
}
// Timer expects @objc selector
@objc func eventWith(timer: Timer!) {
let info = timer.userInfo as Any
print(info)
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-16 14:17:20
Od iOS 10 istnieje również nowa metoda fabryczna timera oparta na blokach, która jest czystsza niż użycie selektora:
_ = Timer.scheduledTimer(withTimeInterval: 5, repeats: false) { timer in
label.isHidden = true
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-21 19:16:39
Swift 3, pre iOS 10
func schedule() {
DispatchQueue.main.async {
self.timer = Timer.scheduledTimer(timeInterval: 20, target: self,
selector: #selector(self.timerDidFire(timer:)), userInfo: nil, repeats: false)
}
}
@objc private func timerDidFire(timer: Timer) {
print(timer)
}
Swift 3, IOS 10 +
DispatchQueue.main.async {
self.timer = Timer.scheduledTimer(withTimeInterval: 20, repeats: false) { timer in
print(timer)
}
}
Uwagi
- musi być w głównej kolejce
- funkcja Callback może być Publiczna, prywatna, ...
- funkcja Callback musi być
@objc
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-16 11:50:10
Sprawdź z:
Swift 2
var timer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: Selector("update"), userInfo: nil, repeats: true)
Swift 3, 4, 5
var timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(self.update), userInfo: nil, repeats: true)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-07-27 17:18:59
Swift 5
Ja osobiście wolę Timer Z Zamknięciem bloku:
Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { (_) in
// TODO: - whatever you want
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-03 11:45:47
Będziesz musiał użyć Timer zamiast NSTimer w Swift 3.
Oto przykład:
Timer.scheduledTimer(timeInterval: 1,
target: self,
selector: #selector(YourController.update),
userInfo: nil,
repeats: true)
// @objc selector expected for Timer
@objc func update() {
// do what should happen when timer triggers an event
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-19 01:19:37
Dla swift 3 i Xcode 8.2 (miło mieć bloki, ale jeśli kompilujesz dla iOS9 i chcesz userInfo):
...
self.timer = Timer(fireAt: fire,
interval: deltaT,
target: self,
selector: #selector(timerCallBack(timer:)),
userInfo: ["custom":"data"],
repeats: true)
RunLoop.main.add(self.timer!, forMode: RunLoopMode.commonModes)
self.timer!.fire()
}
func timerCallBack(timer: Timer!){
let info = timer.userInfo
print(info)
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-30 13:57:41
SimpleTimer (Swift 3.1)
Dlaczego?Jest to prosta klasa timera w języku swift, która umożliwia:
- local scoped timer
- Chainable
- one liners
- użyj regularnych wywołań zwrotnych
Użycie:
SimpleTimer(interval: 3,repeats: true){print("tick")}.start()//Ticks every 3 secs
Kod:
class SimpleTimer {/*<--was named Timer, but since swift 3, NSTimer is now Timer*/
typealias Tick = ()->Void
var timer:Timer?
var interval:TimeInterval /*in seconds*/
var repeats:Bool
var tick:Tick
init( interval:TimeInterval, repeats:Bool = false, onTick:@escaping Tick){
self.interval = interval
self.repeats = repeats
self.tick = onTick
}
func start(){
timer = Timer.scheduledTimer(timeInterval: interval, target: self, selector: #selector(update), userInfo: nil, repeats: true)//swift 3 upgrade
}
func stop(){
if(timer != nil){timer!.invalidate()}
}
/**
* This method must be in the public or scope
*/
@objc func update() {
tick()
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-11 19:21:55
Najpierw zadeklaruj swój timer
var timer: Timer?
Następnie dodaj linię w viewDidLoad () lub w dowolnej funkcji, którą chcesz uruchomić timer
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(action), userInfo: nil, repeats: false)
This is the func you will callback it to do something it must be @objc
@objc func action () {
print("done")
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-21 05:24:38
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(createEnemy), userInfo: nil, repeats: true)
I stwórz zabawę pod nazwą createEnemy
fund createEnemy ()
{
do anything ////
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-07 01:20:01
In Swift 3 coś takiego z @ objc:
func startTimerForResendingCode() {
let timerIntervalForResendingCode = TimeInterval(60)
Timer.scheduledTimer(timeInterval: timerIntervalForResendingCode,
target: self,
selector: #selector(timerEndedUp),
userInfo: nil,
repeats: false)
}
@objc func timerEndedUp() {
output?.timerHasFinishedAndCodeMayBeResended()
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-31 22:24:31
If you INIT method of timer
let timer = Timer(timeInterval: 3, target: self, selector: #selector(update(_:)), userInfo: [key : value], repeats: false)
func update(_ timer : Timer) {
}
Następnie dodaj go do pętli używając metody inny selektor nie zostanie wywołany
RunLoop.main.add(timer!, forMode: .defaultRunLoopMode)
Uwaga: Jeśli chcesz, aby to powtórzyło make repeats true i zachowaj odniesienie do timera, w przeciwnym razie metoda aktualizacji nie zostanie wywołana.
Jeśli używasz tej metody.
Timer.scheduledTimer(timeInterval: seconds, target: self, selector: #selector(update(_:)), userInfo: nil, repeats: true)
Zachowaj odniesienie do późniejszego użycia, jeśli powtórzenia są prawdziwe.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-10 06:51:06
Próbowałem zrobić w klasie NSObject i to mi się udało:
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(300)) {
print("Bang!") }
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-11-27 22:04:29
NSTimer został przemianowany na Timer w Swift 4.2. składnia ta będzie działać w 4.2:
let timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(UIMenuController.update), userInfo: nil, repeats: true)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-12-14 23:56:25