【Swift】Timerの使い方と注意点

本サイトはアフィリエイト広告を利用しています。
Swiftのタイマーについて
  • ひとまず使うのは簡単
  • いくつか注意点があるので気をつけましょう

プログラミングで何か作っていれば、タイマーが必要になることは割とあるのではないかと思います。

Swiftのタイマーは簡単に使うことができるのですが、いくつか注意点があります。

場合によってはメモリリークを起こしたり、タイマーのずれが発生して困るかもしれません。

Timerの使い方

使い方は簡単です。

まずは全体的なサンプルコードです。

import UIKit

class ViewController: UIViewController {

    var sampleTimer: Timer?
    var count: Int = 0
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        cleateTimer()
    }
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        print("second view will disappear")
        
        if sampleTimer != nil {
            sampleTimer?.invalidate()
            sampleTimer = nil
        }
    }
    
    @IBAction func backToFirst(_ sender: Any) {
        dismiss(animated: true)
    }
    
   
    func cleateTimer() {
        
        sampleTimer = Timer.scheduledTimer(timeInterval: 1.0,
                                     target: self,
                                     selector: #selector(self.countUp),
                                     userInfo: nil,
                                     repeats: true)
        
        RunLoop.main.add(self.sampleTimer!, forMode: .common)
    }
    
    @objc func countUp() {
        
        count += 1
        print("\(count)")
    }
}

この中で最低限必要なのは3つあります。

まずは、Timerオブジェクトを用意します。

var sampleTimer: Timer?

それから、次のようにして、タイマーを生成します。

        sampleTimer = Timer.scheduledTimer(timeInterval: 1.0,
                                     target: self,
                                     selector: #selector(self.countUp),
                                     userInfo: nil,
                                     repeats: true)

あとは、タイマーで呼び出す関数を用意します。

    @objc func countUp() {
        
        count += 1
        print("\(count)")
    }

Timer.scheduledTimerの設定を変えることで、タイマー動作を変更できます。

timeIntervalタイマー間隔です。上記のサンプルの場合、1秒間隔で動作します。
repeatsタイマーを繰り返すかどうか。falseにすると一回だけ動作します。

Timerの注意点

Apple Developerサイトをによると、次のような注意点があります。

Timer | Apple Developer Documentation
A timer that fires after a certain time interval has elapsed, sending a specified message to a target object.
Timerの注意点
  • タイマーはランループと連動している。Threading Programming Guide も読んで理解しておく。
  • タイマーは、リアルタイムメカニズムではない。
  • タイマーが発火する実際の時刻は大幅に遅れる可能性がある。Timer Toleranceも参照。
  • 非リピートタイマーは発火した直後に自分自身を無効にする。
  • リピートタイマーはinvalidate()メソッドを呼び出して、自分でタイマーオブジェクトを無効にする必要がある。

精度やタイマーの後始末に気をつける必要がある、ということですね。

タイマーを破棄して後始末

タイマーを無効にしていないと、メモリリークを起こす場合があります。

不要になるタイミング(View will disappear等)で破棄するようにしましょう。

タイマーを破棄するにはinvalidate()を使います。

        if sampleTimer != nil {
            sampleTimer?.invalidate()
            sampleTimer = nil
        }

精度について

特にUIでスクロール処理をしている場合に、タイマーにずれが発生するので注意が必要です。

次のようにすると、対策できます。

        sampleTimer = Timer.scheduledTimer(timeInterval: 1,
                                     target: self,
                                     selector: #selector(self.countUp),
                                     userInfo: nil,
                                     repeats: true)
        // 下記を追加
        RunLoop.main.add(self.sampleTimer!, forMode: .common)  

コメント

タイトルとURLをコピーしました