Swift'te Timer'ı (eski adıyla NSTimer) nasıl kullanabilirim?


258

denedim

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

Ama şunu söylerken bir hata aldım

'(timeInterval: $T1, target: ViewController, selector: () -> (), userInfo: NilType, repeats: Bool) -> $T6' is not identical to 'NSTimer'

1
"NSTimer'i Swift'te nasıl kullanabilirim?" - Objective-C'de kullandığınız gibi. API'sı değişmedi.
Paramanyetik Kruvasan

Yanıtlar:


536

Bu çalışacak:

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
}

Seçiciyi almak istediğiniz Swift 4 için, yöntem Objective-C'ye maruz bırakılmalıdır, bu nedenle @objcöznitelik yöntem bildirimine eklenmelidir.


2
Bu yöntemlerle sınıfın bir NSObject olması gerektiğini ekliyorum, aksi takdirde tanınmayan bir seçim hatasıyla sonuçlanırsınız
Joshua

27
Xcode 6.1 itibariyle, işlev başlığına şöyle bir "@objc" eklemek zorunda kaldım: "@objc func update () {". Bu olmadan uygulama ilk yangın üzerine çöküyor.
kev

Var zamanlayıcı: NSTimer! başlangıçta ve gerektiğinde kullanın!
Nigilan

1
Blok sözdiziminin belki de daha yararlı bir sürümü: let timer = Timer.scheduledTimer (withTimeInterval: timeout, tekrarlar: false) {_ print ("Done.")}
Teo Sartori

'Let timer = Timer (timeInterval: 0.4, tekrarlar: true) {_ baskıda ("Bitti!")}' Kullanamazsınız, bu zamanlayıcıyı başlatmaz ve ardından tekrarlayamazsınız. Timer.scheduledTimer kullanmanız gerekir.
Siamaster

149

Tekrarlanan etkinlik

Aşağıdaki örnekte görüldüğü gibi, bir eylemi birden çok kez yapmak için bir zamanlayıcı kullanabilirsiniz. Zamanlayıcı, etiketi her yarım saniyede bir güncellemek için bir yöntem çağırır.

resim açıklamasını buraya girin

İşte bunun için kod:

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

Geciken etkinlik

Gelecekte bir süre için tek seferlik bir etkinlik planlamak için bir zamanlayıcı da kullanabilirsiniz. Yukarıdaki örnekten ana fark, repeats: falsebunun yerine kullanmanızdır true.

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

Yukarıdaki örnek delayedAction, zamanlayıcı ayarlandıktan iki saniye sonra adlandırılan bir yöntemi çağırır . Tekrar edilmez, ancak timer.invalidate()etkinliği gerçekleşmeden önce iptal etmeniz gerekiyorsa yine de arayabilirsiniz .

notlar

  • Zamanlayıcı örneğinizi birden çok kez başlatma şansınız varsa, önce eski zamanlayıcı örneğini geçersiz kıldığınızdan emin olun. Aksi takdirde zamanlayıcı referansını kaybedersiniz ve artık durduramazsınız. ( bu Soru ve Cevaplara bakın )
  • Gerekmediğinde zamanlayıcıları kullanmayın. İOS Uygulamaları için Enerji Verimliliği Kılavuzu'nun zamanlayıcılar bölümüne bakın .

İlişkili


1
@raddevus, bana bildirdiğiniz için teşekkürler. Eski Swift 3 yorumunu kaldırdım.
Suresi

31

Swift 4'e güncellendi ve userInfo'dan yararlanıldı:

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

}

2
Çalışan bir örnek gösterin, işlev bir NSTimernesne bekliyorsa "özel" ve "veri" ne anlama gelir
Carlos.V

1
Gerçekten önemli değil. İhtiyacınız olan her şeyi userInfo sözlüğüne depolamakta özgürsünüz, bu durumda isteğe bağlı anahtar / değer çiftidir.
igraczech

Bu yararlıdır, ancak Swift 3'te kırılmıştır, çalışma örneği: Timer.scheduledTimer (timeInterval: 1.0, target: self, selector: #selector (event), userInfo: "Gönderilen Bilgi", tekrarlar: true)
Bobby

28

İOS 10'dan itibaren, seçiciyi kullanmaktan daha temiz olan yeni bir blok tabanlı Timer fabrika yöntemi var:

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

1
Yaptığınız gibi, sadece kaldırmak _ = ve başlamakla daha iyi olmaz mıydı Timer?
Bal

2
Kullanılmayan değer hakkındaki uyarıyı susturursanız veya uyarıları önemsemiyorsanız _ = değerini atlayabilirsiniz. Uyarıları ile kodu kontrol etmek istemiyorum.
Josh Homann

22

Swift 3, iOS 10 öncesi

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

notlar

  • Ana kuyrukta olması gerekir
  • Geri arama işlevi genel, özel, ...
  • Geri arama işlevinin @objc

1
Anladığım kadarıyla, yalnızca zamanlayıcı geri aramasının ana kuyrukta olması ve aşağıdakilerin biraz daha verimli olması gerekir: self.timer = Timer.scheduledTimer (withTimeInterval: 20, tekrarlar: false) {DispatchQueue.main.async içinde {timer (timer)}}
Mathieu Frenette

Zamanlayıcım Nesnelerimden birini tetiklemiyordu ve bu hile yaptı :)
Reimond Hill

@ReimondHill Değiştirmeniz gerekiyortimeInterval
onmyway133

17

Şununla kontrol et:

Hızlı 2

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

Hızlı 3, 4, 5

var timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(self.update), userInfo: nil, repeats: true)

2
Ben zaten denedim ama 'sağlanan argümanları kabul' init 'için bir aşırı yük bulunamadı'
yazıyor

1
Aynı şekilde, 'sağlanan argümanları kabul eden' init 'için aşırı yük bulunamadı' hatasını aldım. Bu çizgi gerçekten işe yarıyor mu?
Yangshun Tay

@Yangshun ile aynı hatayı alıyorum. Ne tür bir nesne olmalı self? UIView iyi mi?
SimplGy

@SimpleAsCouldBe: evet sorun değil
Midhun MP

func amountSubmitSuccess () {self.view.hideToastActivity () self.view.makeToast (message: "Miktar Başarılı Bir Şekilde Kayıt Edildi") var timer = NSTimer.scheduledTimerWithTimeInterval (0.5, target: self, selector: "moveToBidderPage", userInfo: nil, repeats: false)} func moveToBidderPage () {let loginPageView = self.storyboard? .instantiateViewControllerWithIdentifier ("bidderpageID") olarak! BidderPage self.navigationController? .PushViewController (loginPageView, canlandırılan: true)}
AG

11

Swift 3'te NSTimer yerine Zamanlayıcı kullanmanız gerekecek .

İşte bir örnek:

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

Hızlı 5

Şahsen zamanlayıcıyı blok kapamayla tercih ediyorum:

    Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { (_) in
       // TODO: - whatever you want
    }

Unutmayın, bu yalnızca macOS 10.12 veya daha yenisinde kullanılabilir. IOS hakkında emin değilim.
jeff-h

İOS'ta da kullanılabilir.
Wissa

7

hızlı 3 ve Xcode 8.2 için (blokları olması güzel, ancak iOS9 için derliyorsanız ve userInfo istiyorsanız):

...

        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)

Neden?

Bu, hızlı bir şekilde, aşağıdakileri yapmanızı sağlayan basit bir zamanlayıcı sınıfıdır:

  • Yerel kapsamlı zamanlayıcı
  • chainable
  • Bir gömlek
  • Düzenli geri aramalar kullanma

Kullanımı:

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

Daha sonra bazı durumlarda bu blok içindeki zamanlayıcı nasıl durdurulur?
Mobil Geliştirici iOS Android

Sadece bir sınıfta zamanlayıcı için ref saklamak sonra sadece çağrı durdurmak. Xcode derleyici kaçış vb gerekiyorsa size söyleyecektir
eonist

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

Ve İsimle Eğlence Yarat createEnemy

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

3

Önce zamanlayıcıyı ilan et

var timer: Timer?

Ardından viewDidLoad () öğesine veya zamanlayıcıyı başlatmak istediğiniz herhangi bir işleve satır ekleyin

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

Bu @objc olmalı bir şey yapmak için geri arayacak fon

@objc func action () {
print("done")
}

2

In Swift 3 @objc ile böyle bir şey:

func startTimerForResendingCode() {
    let timerIntervalForResendingCode = TimeInterval(60)
    Timer.scheduledTimer(timeInterval: timerIntervalForResendingCode,
                         target: self,
                         selector: #selector(timerEndedUp),
                         userInfo: nil,
                         repeats: false)
}




@objc func timerEndedUp() {
    output?.timerHasFinishedAndCodeMayBeResended()
}

1

Zamanlayıcı yöntemini başlatırsanız

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

func update(_ timer : Timer) {

}

sonra diğer seçicinin çağrılmayacağı yöntemi kullanarak döngüye ekleyin

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

NOT: Bunun tekrarlanmasını istiyorsanız, tekrarları doğru yapın ve zamanlayıcı referansını koruyun, aksi takdirde güncelleme yöntemi çağrılmaz.

Bu yöntemi kullanıyorsanız.

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

tekrarlar doğruysa daha sonra kullanmak üzere referans tutun.


0

Bir NSObject Sınıfında yapmaya çalıştım ve bu benim için çalıştı:

DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(300)) {  
print("Bang!") }

-2

Swift 4.2'de NSTimer Timer olarak yeniden adlandırıldı. bu sözdizimi 4.2'de çalışır:

let timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(UIMenuController.update), userInfo: nil, repeats: true)

Yeniden adlandırma Swift 3'te oldu ve diğer cevaplar zaten güncellemeyi yaptı ...
Eric Aya
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.