TimerがFireされなくて、ハマったので、解決策をメモしておきます。
Timerのinitializerには、いろいろなタイプがある
もちろん引数の違いもあるのですが、振る舞い的に大きく2種類に分けられます。
- 自動でスタートする
- 自動ではスタートしない
です。
当たり前に見えるかもしれないのですが、ドキュメントには、あまり分かりやすく書いてありません。
どうやって、識別するか
自動でスタートする/しないは、RunLoopを指定するかどうかの違いです。どのRunLoopでTimerを動かすかを指定したいときには、作成直後に動いて欲しいことはないでしょう。
なので、自分でRunLoopを指定して動かす系のinitializerは、自動では動き始めません。
- scheduledTimer(…)
- 自動で動き始めます。currentのRunLoopとdefaultのmodeで動きます。
- init(…)
- init系はすべて自動では動き始めないので、自分でRunLoopを取得して、add(_:forMode:)でRunLoopに手動で追加する必要があります。
Timerを使うときにハマりやすいこと&解決方法
すこし凝ったことを実装しようとすると、init系で初期化するTimerが必要になるのですが、scheduledTimerから切り替えたときに動かなくなって驚きます。
Initializerの上記の違いを確認して、あわてずに、RunLoopにaddしましょう。
ちなみに、currentのRunLoopでdefaultのmodeならば、以下のコードで追加します。
コード
RunLoop.current.add(timer, forMode: .common)
Sponsor Link