Как я могу использовать 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'

12 ответов


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

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 атрибут должен быть добавлен к объявлению метода.


вот несколько более полных примеров, обновленных для Swift 3.

событие

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

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() если вам нужно отменить событие, прежде чем оно когда-либо произойдет.

Примечания

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

по теме


обновлено до 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)
    }

}

начиная с iOS 10 Существует также новый блок на основе Заводского метода таймера, который чище, чем с помощью селектора:

    _ = Timer.scheduledTimer(withTimeInterval: 5, repeats: false) { timer in
        label.isHidden = true
    }

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

регистрация с:

var timer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: Selector("update"), userInfo: nil, repeats: true);

вам нужно будет использовать таймер вместо 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
}

для swift 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)
    }

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

на 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()
}

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

и создать удовольствие по имени createEnemy

fund createEnemy ()
{
do anything ////
}

Если вы init метод таймера

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)

Примечание: Если вы хотите, чтобы это повторилось, сделайте повторы true и сохраните ссылку на таймер, иначе метод обновления не будет вызван.

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

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

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