今回作成するアプリ
タイマーアプリなどを作る際に、デフォルトでは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