Swift'de her x dakikada bir bir şeyler yapın


Yanıtlar:


171
var helloWorldTimer = NSTimer.scheduledTimerWithTimeInterval(60.0, target: self, selector: Selector("sayHello"), userInfo: nil, repeats: true)

func sayHello() 
{
    NSLog("hello World")
}

Foundation'ı ithal etmeyi unutmayın.

Swift 4:

 var helloWorldTimer = Timer.scheduledTimer(timeInterval: 60.0, target: self, selector: #selector(ViewController.sayHello), userInfo: nil, repeats: true)

 @objc func sayHello() 
 {
     NSLog("hello World")
 }

1
ama ya görünümler arasında geçiş yapmak isterseniz? Kod duracak mı?
Cing

5
@Cing neye atıfta bulunduğuna bağlıdır.
Antzi

1
Unutmayın, NSTimerhedefini koruyor, bu yüzden, bu kurulumla, eğer helloWorldTimerbir özellik varsa , selfkendinize bir tutma döngüsüne sahip olursunuz, burada selftutulan helloWorldTimerve helloWorldTimertutulan self.
MANIAK_dobrii

@MANIAK_dobrii Elde tutma döngüsünün nasıl kırılacağı konusunda da yorum yapabilir misiniz? VC kapatılırsa ancak zamanlayıcı iptal edilmezse, döngü hala dokunuşta mı? Öyleyse, döngüyü kırmak için hem zamanlayıcıyı iptal etmeli hem de görünümü kapatmalısınız?
Dave G

1
Swift 4 için, seçiciyi almak istediğiniz yöntem Objective-C'ye maruz bırakılmalıdır, bu nedenle @objc özniteliği yöntem bildirimine eklenmelidir. örneğin “@objc func sayHello () {}` `
Shamim Hossain

136

İOS sürüm 10 ve üstünü hedefliyorsanız Timer, potansiyel güçlü referans döngülerini basitleştiren blok tabanlı yorumunu kullanabilirsiniz , örneğin:

weak var timer: Timer?

func startTimer() {
    timer?.invalidate()   // just in case you had existing `Timer`, `invalidate` it before we lose our reference to it
    timer = Timer.scheduledTimer(withTimeInterval: 60.0, repeats: true) { [weak self] _ in
        // do something here
    }
}

func stopTimer() {
    timer?.invalidate()
}

// if appropriate, make sure to stop your timer in `deinit`

deinit {
    stopTimer()
}

TimerGenel olarak en iyisi olsa da, bütünlük adına, arka plan iş parçacıkları üzerinde zamanlayıcıları planlamak için yararlı olan gönderim zamanlayıcısını da kullanabileceğinizi belirtmeliyim. Gönderim zamanlayıcıları ile, blok tabanlı olduklarından , kullandığınız sürece eski target/ selectormodel ile bazı güçlü referans döngüsü zorluklarından kaçınır.Timerweak .

Yani:

var timer: DispatchSourceTimer?

func startTimer() {
    let queue = DispatchQueue(label: "com.domain.app.timer")  // you can also use `DispatchQueue.main`, if you want
    timer = DispatchSource.makeTimerSource(queue: queue)
    timer!.schedule(deadline: .now(), repeating: .seconds(60))
    timer!.setEventHandler { [weak self] in
        // do whatever you want here
    }
    timer!.resume()
}

func stopTimer() {
    timer?.cancel()
    timer = nil
}

deinit {
    self.stopTimer()
}

Daha fazla bilgi için, bkz bir Zamanlayıcı Oluşturma bölümünü Sevk Kaynak Örnekler içinde Tevzi Kaynakları bölümünde eşzamanlılık Programlama Kılavuzu.


Swift 2 için, bu cevabın önceki revizyonuna bakın .


Bu yaklaşım dahilinde yalnızca bir kez çalıştırılan bir zamanlayıcıya nasıl gidersiniz?
Juan Boero

@JuanPabloBoero - Bu yaklaşımı bir kez yangın durumunda kullanmazdım. Kullanırdın dispatch_after. Ya da tekrarlamayan NSTimer.
Rob

@Rob Ekranda bir fonksiyondan her saniye güncellenen bir sayaç etiketim var ve sayacımı artırmak ve etiket metnini güncellemek için yukarıdaki kodu kullanıyorum. Ancak, karşılaştığım sorun, sayaç değişkenimin her saniye güncellenmesi, ancak ekranın UILabel'imdeki en son sayaç değerini göstermemesi.
Nagendra Rao

Rao, yukarıdaki bir arka plan iş parçacığı üzerinde bazı eylemler gerçekleştirmek için kullanışlıdır. Ancak kullanıcı arayüzü güncellemeleriniz ana kuyrukta gerçekleşmelidir. Yani, bunu ana iş parçacığında planlayın veya en azından UI güncellemelerini ana iş parçacığına geri gönderin.
Rob

1
Bu soru, bu cevaba yapılan yorumlarda buraya ait değil. Yukarıdaki yorumlarınızı silin ve kendi sorunuzu gönderin. Ancak, kısacası, genellikle uygulamanın arka planda çalışmasını sağlamazsınız, ancak yalnızca olduğu gibi görünmesini sağlarsınız. Stackoverflow.com/a/31642036/1271826 adresine bakın .
Rob

17

İşte NSTimerSwift 3 için ( NSTimerolarak yeniden adlandırıldı Timer) adlandırılmış bir işlev yerine bir kapatma kullanarak yanıt için bir güncelleme :

var timer = Timer.scheduledTimer(withTimeInterval: 60, repeats: true) {
    (_) in
    print("Hello world")
}

6
bu yalnızca iOS 10 içindir.
Glenn

lütfen ios 10+ çözümlerini yayınlamayın
Numan Karaaslan

13

Eğer Eğer bir süre Değişmeye izin burada bazı kod her dakika yürütme basit bir çözüm var:

private func executeRepeatedly() {
    // put your code here

    DispatchQueue.main.asyncAfter(deadline: .now() + 60.0) { [weak self] in
        self?.executeRepeatedly()
    }
}

Sadece bir executeRepeatedly()kez çalıştırın ve her dakika yürütülür. Yürütme, sahip olan nesne ( self) serbest bırakıldığında durur . Ayrıca, yürütmenin durması gerektiğini belirtmek için bir bayrak da kullanabilirsiniz.


Bu karar, tüm bu zamanlayıcıların etrafında olmaktan, onları runloop'lara eklemek, geçersiz kılmaktan çok daha uygundur ... Harika!
julia_v

bu geçerli bir çözüm gibi görünüyor, ancak web servis
çağrımla kullandığımda bir saklama

11

Kullanabilirsiniz Timer(swift 3)

var timer = Timer.scheduledTimerWithTimeInterval(60, target: self, selector: Selector("function"), userInfo: nil, repeats: true)

Selector () 'a işlev adınızı yazarsınız


Bunu hızlı 3'te nasıl yapabilirsiniz?
bibscy

1
use Timer... NSTimeryeniden adlandırıldı
Joseph

7

Hızlı 3.0'da GCD yeniden düzenlendi:

let timer : DispatchSourceTimer = DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue.main)

timer.scheduleRepeating(deadline: .now(), interval: .seconds(60))
timer.setEventHandler
{
    NSLog("Hello World")
}
timer.resume()

Bu, özellikle belirli bir Kuyrukta gönderim yapmanız gerektiğinde kullanışlıdır. Ayrıca, bunu kullanıcı arabirimi güncellemesi için kullanmayı planlıyorsanız CADisplayLink, GPU yenileme hızı ile senkronize edildiğinden bakmanızı öneririm .

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.