Swift、Timer、一時停止のやり方
謎のプリン語る。
プログラミングの役立つ、エンジニア技術情報とか、どうでもいい雑談とか書いてます。
一人書く人増えました。
Swift、Timer、一時停止のやり方
※この記事は9年以上前の記事です。
現在は状況が異なる可能性がありますのでご注意ください。
どうも、Swift、はまってます、みやびです。
表記の件、簡単にできるかなと思いきや、なかなかめんどくさかったので、覚書的に記事を書いてみようと思う。
Google先生に聞いてみると真っ先に出てくるのは下記の方法。
class GameViewController: UIViewController {
// タイマー変数を用意
var gameClearTimer: Timer?;
override func viewDidLoad() {
super.viewDidLoad()
self.gameClearTimer = Timer.scheduledTimer(timeInterval: 60, target: self, selector: #selector(GameViewController.clearFunc), userInfo: nil, repeats: false);
}
// タイマーを止めたり動かしたりするメソッド
func timerStopStart(setFlg: Bool){
if setFlg {
// タイマーを再開する
self.gameClearTimer?.fire();
} else {
// 一時停止をする
self.gameClearTimer?.invalidate();
}
}
// 終了時実行
func clearFunc(){
print("ゲーム終了");
}
}
一時停止は、Timerクラスの、invalidateメソッド、
再スタートは、fireメソッドを実行すればいい。
っていう記事がほとんどだが、これ、
動かないんだヨ!
そう、確かに、Timerの止め方は、invalidateで合ってるんだが、
そのメソッドを実行した時点で、Timerインスタンスは死んでしまうのだ。
なので、fireメソッドをいくら叩いても、タイマーはうんともすんとも言わない。
タイマーをセットし直さなければいけないのだ。
しかし、そうなると、例えば、60秒後に、なにかやるってタイマーで、
10秒経った時に停止、また再開、となると、また60秒タイマーになるので、
10秒多くなってしまう。
じゃぁどうするかというと下記の方法をとる
class GameViewController: UIViewController {
// タイマー変数を用意
var gameClearTimer: Timer?;
// 時刻を取る変数を用意
let gameStartTime: Date = Date();
var gamePauseTime: Date = Date();
override func viewDidLoad() {
super.viewDidLoad()
self.timerStopStart();
}
// 一時停止を実行するメソッド
func pauseBtnFunc(){
// 一時停止時刻を変数に入れる
self.gamePauseTime = Date();
// 一時停止をする(タイマーを削除)
self.timerStopStart(false);
}
// タイマーを止めたり動かしたりするメソッド
func timerStopStart(setFlg: Bool){
if setFlg || self.gameClearTimer == nil {
// 一時停止時間から、最初の時間を引いて、その分をタイマーセット時間から引く
let defTime = self.gamePauseTime.timeIntervalSince1970 - self.gameStartTime.timeIntervalSince1970;
// タイマーを入れなおす
self.gameClearTimer = Timer.scheduledTimer(timeInterval: 60 - defTime, target: self, selector: #selector(GameViewController.clearFunc), userInfo: nil, repeats: false);
} else {
self.gameClearTimer?.invalidate();
}
}
// 終了時実行
func clearFunc(){
print("ゲーム終了");
}
}
つまりは、最初のスタート時間と、一時停止時間を取っておいて、
再度タイマーをセットするとき、一時停止時間から、スタート時間の差分を出して、
その分を、タイマーセットの時間から引くってわけだ。
こうすれば、一時停止を再現できる。
繰り返しの場合は、もう少しめんどいが、今回のスクリプトの応用でできるはずだ。
ここらへん、もっと便利な関数作ってくれんかね、マジ・・・。
そして、invalidateのことを一時停止と紹介している記事があまりにも多すぎる。
ちゃんと検証してから記事書いてほしいもんや。
(人のこと言えないけどな)