【Swift UIKit】ストップウォッチタイマーの実装方法!Timerクラスの使い方
この記事からわかること
- SwiftのUIKitでストップウォッチでタイマーを実装する方法
- Timerクラスの使い方
- 時間や分、秒を表示させる方法
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
今回はゲーム開発などに使いがちなタイマー機能(ストップウォッチ)をSwiftで実装する方法をまとめていきたいと思います。
Swiftでストップウォッチタイマーを作るには?
ポイント
- Timerクラス
- 経過時間の表示方法
タイマー機能を実装するためにはTimerクラスが重要になってきます。
実装の流れ
- StoryboardからUI部品(ラベルとボタン)を配置
- アウトレット変数を定義し紐付け
- Timerクラスでタイマー操作
今回はStoryboardを使用した場合で解説していきます。Swift UIでもストップウォッチのロジックは変わらないのでそのまま流用してみてください。
実装方法
StoryboardからUI部品(ラベルとボタン)を配置
Storyboardにタイマー表示用のUILabelとスタート/ストップ用のUIButtonを2つ配置しておきます。
アウトレット変数を定義し紐付け
続いてViewControllerクラスにIBOutlet
とIBAction
を定義しStoryboardのUIと紐付けをしておきます。
@IBOutlet weak var timeLabel:UILabel!
@IBAction func startBtnTapped() {
//
}
@IBAction func stopBtnTapped() {
//
}
これで前準備は整いました。ここからタイマーのロジック部分に入っていきます。
Timerクラスでタイマー操作
まずは経過時間を保持するtime
プロパティとTimer
インスタンスを保持するtimer
プロパティを用意します。
private var time:Double = 0.0
private var timer:Timer = Timer()
続いてタイマーをスタートさせる処理を記述します。Timer.scheduledTimer
の使い方に関しては後述します。ここでは0.01秒ごとにtime
プロパティの値を0.01ずつ増やしています。
time
プロパティが保持するのは経過した秒数(ミリ秒も含む)のみなのでこれを時間や分数、秒数などに整形しておきます。
@IBAction func startBtnTapped() {
timer = Timer.scheduledTimer(withTimeInterval: 0.01, repeats: true, block: { [self] _ in
self.time += 0.01
let minutes = Int(self.time / 60)
let second = Int(self.time) % 60
let milliSecond = Int(self.time * 100) % 100
self.timeLabel.text = String(format: "%02d:%02d:%02d", minutes, second, milliSecond)
})
}
最後に動いているタイマーを一時停止させるためのボタン処理を記述します。
@IBAction func stopBtnTapped() {
self.timer.invalidate()
}
これでストップウォッチタイマーが完成しました。最後に全体のコードを載せておきます。
全体のコード
import UIKit
class ViewController: UIViewController{
private var time:Double = 0.0
private var timer:Timer = Timer()
@IBOutlet weak var timeLabel:UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func startBtnTapped() {
timer = Timer.scheduledTimer(withTimeInterval: 0.01, repeats: true, block: { [self] _ in
self.time += 0.01
let minutes = Int(self.time / 60)
let second = Int(self.time) % 60
let milliSecond = Int(self.time * 100) % 100
self.timeLabel.text = String(format: "%02d:%02d:%02d", minutes, second, milliSecond)
})
}
@IBAction func stopBtnTapped() {
self.timer.invalidate()
}
}
Timerクラス
class Timer : NSObject
Timerは指定した任意の時間経過後に任意の処理を実行できる機能を提供するクラスです。
そして肝となるのがscheduledTimer
メソッドです。
scheduledTimerメソッド
scheduledTimer
メソッドは同名の引数違いで3種類ほど用意されていますが今回使用しているのはscheduledTimer(withTimeInterval:repeats:block:)
になります。
class func scheduledTimer(
withTimeInterval interval: TimeInterval,
repeats: Bool,
block: @escaping @Sendable (Timer) -> Void
) -> Timer
3つの引数
- interval:タイマーの発火秒数
- repeats:指定秒数ごとに繰り返すかどうか
- block:発火ごとに繰り返したい処理
おすすめ記事:【Swift】completionHandlerとは?使い方と@escapingの意味
返り値として指定されたパラメータで構成されたTimerオブジェクトが返ります。
self.timer = Timer.scheduledTimer(withTimeInterval: 0.01, repeats: true, block: { [self] timer in
// 任意の処理
})
タイマーの停止:invalidateメソッド
動き出したタイマーを停止させるにはinvalidate
メソッドを実行します。このメソッドは実行されているTimerオブジェクトから呼び出す必要があるのでscheduledTimer
メソッドで帰ったオブジェクトから呼び出します。
self.timer.invalidate()
経過時間の表示方法
今回は経過時間が秒単位(小数点含むDouble型)で保持されています。ユーザーの目には秒ではなく、時間や分数、秒数、ミリ秒数で表示させたいのでそれぞれ算出していきます。
それぞれの計算方法
let time = 3850.45
let hour = Int(time / 3600)
let minutes = Int(time / 60)
let second = Int(time) % 60
let milliSecond = Int(time * 100) % 100
let displayTime = String(format: "%02d:%02d:%02d:%02d",hour,minutes,second,milliSecond)
// 01:64:10:45"
// 時間:経過時間 ÷ (60分 × 60秒)の商
// 分数:経過時間 ÷ 60秒の商
// 秒数:経過時間 ÷ 60 の余り
// m秒:(経過時間 × 100) ÷ 100 の余り
// 3850.45 × 100 = 385045
// 385045 ÷ 100 = 3850(商) … 45(余り) ←
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。