Swift、Timer、一時停止のやり方

謎のプリン語る。
プログラミングの役立つ情報とか、どうでもいい雑談とか書いてます。
一人書く人増えました。

Swift、Timer、一時停止のやり方

みやびプリン 500 316

500 320

Swift、Timer、一時停止のやり方 - サムネイル

※この記事は7年以上前の記事です。
現在は状況が異なる可能性がありますのでご注意ください。

どうも、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のことを一時停止と紹介している記事があまりにも多すぎる。
ちゃんと検証してから記事書いてほしいもんや。
(人のこと言えないけどな)

ゲーム、アニメ、イラストなどを学びたい方必見!【アミューズメントメディア総合学院】 - メイン

トラックバック(0)

トラックバックURL:

コメント(2)

坂本廉

| 2017年9月17日 23:24 | 返信

初めまして
カウントダウンタイマーの一時停止についてどうすればいいかが分からなく色々自分なりに調べたり、ネットなどで検索かけたりして偶然この記事に出会えたて、ちょうど自分のやりたいことについて書いてあってとても参考になりました。それでなんですが、参考にはなったのですがswiftについて勉強し始めたばかりなので一部だけのコードだと分かりづらいの全コード見せて頂けませんか?

●みやびプリンから坂本廉への返信

| 2017年10月10日 17:53 | 返信

コメント、大変にありがとうございます。
そして、返信が遅くなりすみません!

そうですね、コードに関しては、
エントリー内で紹介しているファイルに関しては、ほぼほぼすべてのコードなのですが、実際どう使うかは記載しておりません。
他のファイルも含めてなら、使い方を含めての紹介になるかと思いますので、メールにてzipファイルをお送りします。
(恥ずかしながら、Gitの公開の仕方がわからないので 汗)

またご連絡します。

コメントする

ページトップへ戻る