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'
Author: vacawama, 2014-06-03

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.

 542
Author: Oscar Swanros,
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.

Tutaj wpisz opis obrazka

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

 153
Author: Suragch,
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)
    }

}
 31
Author: igraczech,
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
    }
 29
Author: Josh Homann,
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
 23
Author: onmyway133,
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)
 17
Author: Midhun MP,
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
    }
 13
Author: Wissa,
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
}
 11
Author: Ondrej Kvasnovsky,
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)
    }
 7
Author: ingconti,
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()
    }
}
 6
Author: eonist,
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")
}
 6
Author: Gerges Eid,
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 ////
}
 3
Author: Khaled Hamdy,
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()
}
 2
Author: Nik Kov,
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.

 1
Author: Surjeet Rajput,
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!") }
 0
Author: Álvaro Agüero,
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)
 -2
Author: Jamtrax Reunion,
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