今回作成するアプリ

タイマーアプリなどを作る際に、デフォルトでは1, 2, 3秒など秒単位までしか表示することができません。
しかし、もっと細かいミリ秒(mm)で表示したい場合もあると思います。
そこで、今回はSwiftUIでミリ秒単位で時間を表示する方法をご紹介します。
実装
コード
import SwiftUI
struct ContentView: View {
@State private var timeInterval: TimeInterval = 0
private let formatter = TimerFormatter()
private let timer = Timer.publish(every: 0.01, on: .main, in: .common).autoconnect()
var body: some View {
Text(NSNumber(value: timeInterval), formatter: formatter)
.font(.system(size: 50, weight: .light, design: .monospaced))
.onReceive(timer) { _ in timeInterval += 0.01 }
.padding()
}
}
class TimerFormatter: Formatter {
let componentFormatter: DateComponentsFormatter = {
let formatter = DateComponentsFormatter()
formatter.allowedUnits = [.hour, .minute, .second]
formatter.zeroFormattingBehavior = .pad
return formatter
}()
override func string(for obj: Any?) -> String? {
guard let time = obj as? TimeInterval else { return nil }
guard let formattedString = componentFormatter.string(from: time) else { return nil }
let hunredths = Int((time.truncatingRemainder(dividingBy: 1)) * 100)
let decimalSperator = Locale.current.decimalSeparator ?? "."
return String(format: "%@%@%0.2d", formattedString, decimalSperator, hunredths)
}
}解説
ContentViewは、Viewプロトコルに準拠する構造体で、タイマーの時間間隔を追跡するために、@StateプロパティtimeIntervalを使用しています。このプロパティは、0で初期化されます。
Textビューは、時間間隔を表示するために使用されます。このTextビューには、NSNumberとFormatterが渡されます。NSNumberは、timeIntervalプロパティの値を表し、Formatterは、TimerFormatterオブジェクトが割り当てられています。
TimerFormatterは、Formatterクラスを継承するカスタムフォーマッタークラスです。このクラスは、string(for:)メソッドを実装しています。このメソッドは、タイマーの時間間隔を受け取り、それをフォーマットして、時、分、秒、および100分の1秒の形式で返します。
ContentViewには、timerという名前のTimerがあります。このtimerは、Timer.publish(every:on:in:)メソッドを使用して、0.01秒ごとに実行されるTimerオブジェクトを作成します。autoconnect()メソッドは、Timerオブジェクトを自動的に接続します。このタイマーは、.onReceive(_:)メソッドを使用して、時間間隔を更新し、ビューを再描画します。
最後に、ビューには、padding()メソッドが追加されています。これにより、テキストがビューの端から離れるように設定されます。
動作
環境
macOS Ventura 13.0.1
Xcode 14.2
iOS 16.2
アイキャッチ画像 出典: App.com