
Swiftで時間に応じた処理をしたいときに便利なのが Timer.publish
です。
SwiftUIアプリでも「一定間隔でデータを更新する」「カウントダウンを作る」など、様々な場面で活用できます。
この記事では Timer.publish
の意味や使い方、引数の意味、似た機能である TimelineView
との違いまでをもわかりやすく解説します。
Timer.publishとは?
Timer.publish
は、一定間隔でイベントを発行する Combine のパブリッシャーです。
これを SwiftUI の .onReceive
と組み合わせることで、定期的なタイマー処理をUIに組み込むことができます。
例えば「1秒ごとにカウントダウンを表示する」「5秒ごとにデータを更新する」といった処理が可能になります。
基本構文は以下のようになります:
1 2 |
Timer.publish(every: 秒数, on: .main, in: .common).autoconnect() |
このタイマーは Combine のパブリッシャーなので、.onReceive
や .sink
などと連携して使います。
具体例:1秒ごとにカウントアップする
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import SwiftUI import Combine struct ContentView: View { @State private var counter = 0 let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect() var body: some View { Text("カウント: \(counter)") .onReceive(timer) { _ in counter += 1 } } } |
counter
の値が1つずつ増えていきます。
autoconnect()
を使うことで、View
が表示されたタイミングで自動的にタイマーが開始されます。
主要な引数と意味
Timer.publish には以下のような引数があります。
引数名 | 説明 |
---|---|
every | イベントの発行間隔(秒単位)。例:1 → 1秒ごと |
on | 実行する RunLoop(通常は .main ) |
in | RunLoopのモード(通常は .common ) |
every
で「何秒ごとにイベントを発行するか」を決めます。
on
と in
は少しわかりにくいですが、これは「タイマーをどの処理ループに乗せるか」を指定しています。
RunLoop(ランループ) とは、アプリが「お客さんを待つ店員さん」のように、ユーザーからの操作やシステムからの通知をじっと待ち続ける仕組みのことです。
iOSアプリは常にRunLoopの中でユーザー操作やシステムイベントを監視・処理しており、Timer
もこのRunLoopに登録されることで定期的に発火します。
通常は .main
(メインスレッドのRunLoop)+ .common
(一般的なモード)を使えば十分です。
これにより、UI更新と同じタイミングでタイマーが動作し、表示の更新がスムーズに行えます。
例えば、every: 1, on: .main, in: .common
と指定すれば「メインスレッドで1秒ごとにイベントを発行するタイマー」が作成されます。
autoconnectとは?
.autoconnect()
は、タイマーの接続を自動的に開始してくれる便利なメソッドです(これは、Combine フレームワークの Publishers.Autoconnect に含まれています。)
これを指定しないと、.connect()
を明示的に呼ぶ必要があり、コードが少し複雑になります。
SwiftUI で使う場合は基本的に .autoconnect()
をつけて .onReceive
とセットで使うのが一般的です。
TimelineViewとの違いと使い分け
Timer.publish と似た用途で使えるものに SwiftUI の TimelineView
があります。
どちらも時間に応じた更新を行いますが、それぞれ使いどころが異なります。
Timer.publishは Combine ベースの汎用的なタイマーで、状態の変化を扱う場面に向いています。
一方、TimelineView は描画更新に特化した SwiftUI の構造で、現在時刻の秒表示やフレームごとのアニメーション描画などに適しています。
Timer.publish の特徴
- Combine ベースのタイマー
- onReceive を使って状態を更新
- 状態を持つUIロジックに向いている(カウントダウンなど)
- SwiftUI以外のロジックにも応用可能
TimelineView の特徴
- SwiftUI専用のView構造
- フレームや時間ごとにViewを自動更新
- 現在時刻の表示やアニメーションに最適
- 状態変化を伴わない描画処理向き
簡単な使い分けの目安としては以下の通りです。
目的 | 使うべきもの |
---|---|
カウントダウンや定期処理 | Timer.publish |
現在時刻を秒単位で表示 | TimelineView |
データを一定間隔で取得 | Timer.publish |
Viewを毎秒更新したいだけ | TimelineView |
Timer.publish の活用シーン
Timer.publish は以下のような場面で活躍します。
- カウントダウンやカウントアップタイマー
- 定期的なデータ取得処理(APIポーリングなど)
- 一定時間後に非表示にする処理
- バッジや通知などのスケジューリング
- アニメーションやゲーム処理のトリガー
Combine のパブリッシャーとして使えるため、非SwiftUIなロジックや ViewModel 層にも組み込める点が強みです。
Timer.publish を使うときの注意点
Timer.publishを使う上で下記の点には注意しておきましょう。
- Viewが消えてもタイマーが止まらないことがある(メモリリークに注意)
.autoconnect()
によって予期せぬタイミングで処理が走る可能性がある- 画面外での動作制御が必要な場合は
.connect()
/.cancel()
を使って明示的に管理すべき - 秒数の精度は保証されない(正確なタイマー用途には不向き)
まとめ
今回は Swift の Timer.publish について詳しく解説しました。
- Timer.publish は Combine ベースの定期イベント発行ツール
- SwiftUI と組み合わせることで、onReceive でタイマー処理を実現可能
- autoconnect を使えばタイマー接続が自動化される
- TimelineView とは目的が異なり、状態変化が必要なら Timer.publish、描画だけなら TimelineView が適している
タイマー処理はアプリ開発で非常によく使われる技術のひとつです。
Timer.publish の仕組みを理解しておくことで、より柔軟に時間制御を実装できるようになります。
ぜひ試してみてくださいね!