Как я могу использовать Timer (ранее NSTimer) в Swift?

Я пробовал

var timer = NSTimer()
timer(timeInterval: 0.01, target: self, selector: update, userInfo: nil, repeats: false)

Но я получил сообщение об ошибке

'(timeInterval: $T1, target: ViewController, selector: () -> (), userInfo: NilType, repeats: Bool) -> $T6' is not identical to 'NSTimer'
+239
источник поделиться
15 ответов

Это будет работать:

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
}

Для Swift 4, метод, для которого вы хотите получить селектор, должен быть открыт для Objective-C, поэтому атрибут @objc должен быть добавлен в объявление метода.

+516
источник

Повторное событие

Вы можете использовать таймер для выполнения действия несколько раз, как показано в следующем примере. Таймер вызывает метод для обновления метки каждые полсекунды.

enter image description here

Вот код для этого:

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)"
    }
}

Задержка события

Вы также можете использовать таймер, чтобы запланировать одноразовое событие на какое-то время в будущем. Основное отличие от приведенного выше примера состоит в том, что вы используете repeats: false вместо true.

timer = Timer.scheduledTimer(timeInterval: 2.0, target: self, selector: #selector(delayedAction), userInfo: nil, repeats: false)

В приведенном выше примере вызывается метод с именем delayedAction через две секунды после установки таймера. Это не повторяется, но вы все равно можете позвонить в timer.invalidate(), если вам нужно отменить событие до того, как оно произойдет.

Примечания

  • Если есть шанс запустить экземпляр таймера несколько раз, убедитесь, что сначала вы сделали недействительным старый экземпляр таймера. В противном случае вы потеряете ссылку на таймер и больше не сможете его остановить. (см. этот вопрос & A)
  • Не используйте таймеры, когда они не нужны. См. раздел "Таймеры" в Руководстве по энергоэффективности для приложений для iOS.

Связанные

+141
источник

Обновлено до Swift 4, используя 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)
    }

}
+29
источник

Как и в iOS 10, также существует новый метод Timer factory на основе блоков, который более чист, чем при использовании селектора:

    _ = Timer.scheduledTimer(withTimeInterval: 5, repeats: false) { timer in
        label.isHidden = true
    }
+25
источник

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)
      }
    }

Примечания

  • Он должен находиться в главной очереди
  • Функция обратного вызова может быть общедоступной, частной,...
  • Функция обратного вызова должна быть @objc
+21
источник

Проверьте с помощью:

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)
+15
источник

Вам нужно будет использовать таймер вместо NSTimer в Swift 3.

Вот пример:

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
источник

для быстрых 3 и Xcode 8.2 (приятно иметь блоки, но если вы компилируете для iOS9 И хотите 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)
    }
+6
источник

SimpleTimer (Swift 3.1)

Почему?

Это простой класс таймера в swift, который позволяет вам:

  • Локальный таймер
  • змеевидных
  • Один вкладыш
  • Использовать регулярные обратные вызовы

Использование:

SimpleTimer(interval: 3,repeats: true){print("tick")}.start()//Ticks every 3 secs

Код:

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()
    }
}
+5
источник
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(createEnemy), userInfo: nil, repeats: true)

И создать Fun по имени createEnemy

fund createEnemy ()
{
do anything ////
}
+3
источник

В Swift 3 что-то вроде этого с @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
источник

Если вы запускаете метод таймера

let timer = Timer(timeInterval: 3, target: self, selector: #selector(update(_:)), userInfo: [key : value], repeats: false)

func update(_ timer : Timer) {

}

затем добавьте его в цикл, используя метод другого селектора, который не будет называться

RunLoop.main.add(timer!, forMode: .defaultRunLoopMode)

ПРИМЕЧАНИЕ. Если вы хотите, чтобы это повторялось, повторите повторение и сохраните ссылку на таймер, иначе метод обновления не будет вызываться.

Если вы используете этот метод.

Timer.scheduledTimer(timeInterval: seconds, target: self, selector: #selector(update(_:)), userInfo: nil, repeats: true)

сохраните ссылку для последующего использования, если повторы верны.

+1
источник

Swift 5

Я лично предпочитаю Таймер с закрытием блока:

    Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { (_) in
       // TODO: - whatever you want
    }
+1
источник

Сначала объявите свой таймер

var timer: Timer?

Затем добавьте строку в viewDidLoad() или в любую функцию, для которой вы хотите запустить таймер.

timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(action), userInfo: nil, repeats: false)

Это функция, которую вы перезвоните, чтобы сделать что-то, что должно быть @objc

@objc func action () {
print("done")
}
0
источник

NSTimer был переименован в Timer в Swift 4.2. этот синтаксис будет работать в 4.2:

let timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(UIMenuController.update), userInfo: nil, repeats: true)
-1
источник

Посмотрите другие вопросы по меткам или Задайте вопрос