【Swift】加算型Timer(ストップウォッチみたいな)の作り方 〜Timerの基本的な使い方〜

【Swift】加算型Timer(ストップウォッチみたいな)の作り方 〜Timerの基本的な使い方〜

Swiftにてストップウォッチの様な 加算型のTimer を作りたかったので、備忘録。
今回は TimerscheduledTime関数 を利用して、加算型Timerを作成します。
 

Timer.scheduledTimer のサンプル

まずは先に全体のサンプルを。。

 

各箇所を詳しく説明

① Timer のスケジューリングと保持

scheduledTi関数 は下記の引数を指定して、実行します。

引数名 指定する要素
timeInterval タイマーが発火する秒数を指定
target selector に支持する関数を持っているインスタンス指定
selector 実行する関数を指定
userInfo 関数に引き渡したいDictionaryを指定
repeats 繰り返しをするか否かを指定

実行すると Timer が生成されて、自動的にスケジューリングされ動き始めます
timeInterval で指定した時間がすぎると、selector で指定した関数が実行されます。
scheduledTimer関数 は実行されると生成した Timerを返却するので、上記の例だと var timerTimer が格納されます。
 

② Timer の間隔秒を総秒数に加算する

今回は加算型のタイマーを作るのが目的なので、クラスが持つ var timerTotalDuration に経過した時間を加算していきます。
timeInterval5 を設定していたら5秒毎に handleTimer関数 が実行され、timer.timeInterval に格納されている 5timerTotalDuration に加算されていきます。
 

③ Timer のスケジューリングを破棄

今回はストップウォッチのように タイマーを一時停止 できるようにします。
ですが、 Timer のスケジュール自体をストップすることは出来ず、invalidate関数 で一度 Timer 自体を破棄しなければいけません。
再度タイマーを動かしたい時には scheduledTimer関数 をもう一度実行して、同じ設定の Timer を作り直す必要があります。

上記サンプルでは、startTimer()Timer が生成され、stopTimer() で破棄されます。
ですが経過した秒数は timerTotalDuration に保持してあるので、再開したい場合は startTimer() を実行し、新しい Timer で計測を再開します。
 

④ Timer のスケジューリングを破棄し、総秒数を0に戻す

この箇所はいわゆる初期化になります。
stopTimer関数Timer を破棄(ストップ)し、加算していた総秒数を 0 に戻します。
これで、再度 startTimer関数 が実行された際には 0 からのカウントになります。
 

⑤ Timer のスケジューリング重複を回避

最後に⑤の箇所になりますが、この箇所は Timer を利用する際に気をつけたい部分 となります。

scheduledTimer関数 実行前に、var timerTimer が格納されていないかチェックしていますが、これは必ず行った方が良い判定です
というのも、scheduledTimer関数 を実行すれば Timer をいくらでも生成できてしまい、その都度新しい Timer が返却されてしまうからです。

例として下記のように実行した場合、参照を無くしたタイマーが発火し続ける事になります。

なので、必ず破棄していない Timer への参照を失わないようにすべきです。

更に注意すべきなのは。scheduledTimer関数に指定する target によっては循環参照になるので、Timer を破棄しない限り、target に指定したインスタンスも解放されなくなります

つまり、Timer の参照はしっかり管理し、target に指定しているインスタンスが破棄されるべきタイミングで、必ず invalidate関数 を呼ばなければなりません。
そういったリスクを踏まえ、⑤の処理は必ず入れておく事をおすすめします。
 

合わせて注意したい事

【Swift】Timerがズレる (遅延する) 時の原因と対処法
【Swift】Timerの強参照が破棄できない時の対処法(deinit での破棄方法)
 

Info. ドキュメント

公式ドキュメント
 

Info. サンプルテスト環境

Mac OS: 10.13.6
Xcode: Version 10.0