【Swift】タイマー機能(カウントダウン)を実装する

初めてタイマー機能を設置したのでメモ書き程度に。

タイマーを生成する

タイマーを生成します

let myTimer:Void = NSTimer.scheduledTimerWithTimeInterval(
            1.0,
            target:self,
            selector:"timerAction:",
            userInfo:nil,
            repeats:true
)
            .fire()

タイマーを生成するときにはNSTimerを使います。

scheduledTimerWithTimeIntervalはタイマーを発生させる間隔のことで、今回は1秒に設定しています。

targetはタイマーが発生したときに呼び出すターゲットがあるメソッドを書きます。今回はselfです。

selectorにはタイマーが発生したときのアクション(呼び出すメソッド)を書きます。

userInfoはselectorで呼び出すメソッドに渡す情報です。

repeatsはタイマーの実行を繰り返すかどうか、です。

 

タイマーを繰り返すっていう表現がイマイチピンと来なくて、むむむってなったんですが、NSTimerでは一定間隔ごとにあるメソッドを呼び出すもの、と考えた方がわかりやすかったです。

 

タイマー内の処理

タイマー内の処理を書いていきます。

これはNSTimerにより1秒ごとに呼び出されます。

先にラベルを用意しておきます

  /*時間*/
    let timeLabel = UILabel()
    timeLabel.frame = CGRect(x:15,y:8,width:30,height:50)
    view.addSubview(timeLabel)
  /*秒*/
    let secondLabel = UILabel()
    secondLabel.frame = CGRect(x:42,y:43,width:30,height:10)
    view.addSubview(secondLabel)

時間を表示するラベルをtimeLabel、秒or分を表示するラベルをsecondLabelとしました。

 

今回は3分のタイマーを作ります

let userTimer = 3   //(分)
var count = userTimer * 60

分の定数を用意したら、それを秒数に直します

 

そしてタイマーが発生したときに呼び出されるメソッドを書いていきます

func timerAction(sender:NSTimer){
     //1分以上の場合は分で表示する
     if  count >= 60 {
         let minuteCount = count / 60       
         timeLabel.text = String(minuteCount)
         secondLabel.text = "分"
         count--
     }
     //1分未満の場合は秒で表示する
   else if count < 60{
         timeLabel.text = String(count)
         secondLabel.text = "秒"
           if count == 0{
                  //タイマーが終わったときの処理
                 sender.invalidate()
             }
          count--
      }
}

 

初めのifで1分以上の場合は分で表示するための処理を書きます。

次のelse ifで1分未満になった場合は秒数で表示するための処理を書きます。

 

0になっときにタイマーを止めるために書くコードがこれです

sender.invalidate()

 

 

今回のタイマーでは、3分の間は常に3分と表示し、59秒から0秒までを秒で表示するようにしました。

表示としては3分 2分 1分 59秒 58秒・・・・2秒 1秒 0秒 となります。

 

全体のコード

import UIKit


class ViewController: UIViewController {

    let timeLabel = UILabel()
    let secondLabel = UILabel()    

    override func viewDidLoad() {
        super.viewDidLoad()
        timeLabelFunc()
        timerFunc()
}
func timeLabelFunc(){ 
       /*時間*/
        timeLabel.frame = CGRect(x:15,y:8,width:30,height:50)
        timeLabel.font = UIFont.systemFontOfSize(22)
        timeLabel.textAlignment = NSTextAlignment.Center
        view.addSubview(timeLabel)
        /*秒*/
        
        secondLabel.frame = CGRect(x:42,y:43,width:30,height:10)
        secondLabel.font = UIFont.systemFontOfSize(10)
        view.addSubview(secondLabel)
    }    
//ユーザーが指定した時間(仮) 分
    let userTimer:Int = 1
    var count = 0
    /*タイマーの作成*/
    func timerFunc(){
        count = userTimer * 60
        let myTimer:Void = NSTimer.scheduledTimerWithTimeInterval(
            1.0,
            target:self,
            selector:"timerAction:",
            userInfo:nil,
            repeats:true)
            .fire()
    }
    //タイマーの処理
    func timerAction(sender:NSTimer){
        if count >= 60 {
            let minuteCount = count / 60
            
            timeLabel.text = String(minuteCount)
            secondLabel.text = "分"
            count--
        }

        else if count < 60{
            timeLabel.text = String(count)
            secondLabel.text = "秒"
            if count == 0{
                sender.invalidate()
            }
            count--
        }
        
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

 

なぜかカウントが上手くいかなかったりしたんですけど、1減らす部分の場所が悪いなどの、書く位置が悪い!ということがよくありました。。

基本は上から処理しているよってことをあまり気にせずにやっているとおかしな挙動になったりするので注意が必要です。。

 

次はいよいよお絵描き編かもしれないです。

2018/04/14追記 Swift4に対応してみました。
ザックリですが。

(´ε`;)ウーン…
NSTimerをTimerに変えたぐらいですね。
Swift ,
コメントは認証制です。詳しくは下記の注意をお読みください。お気軽にコメントお願いします!

Write a Comment

コメント時の注意

「Twitter」「Facebook」「Google+」「WordPress」のいずれかのアカウントをお持ちの方は各アカウントと連携することでコメントできます。 コメントしたことはSNSに流れませんので、アカウントをお持ちの方はこちらの方法でコメントを投稿して下さると嬉しいです。 アカウントをお持ちでない方はメールアドレスで投稿することができます。 初回コメント時は承認後に表示されます。

Related Memo...

記事を書くほどでもないけれどメモっておきたいこと

テスト投稿。

例えばiphone7 の画面サイズ

750 × 1334
半分375 × 667

iOS

UINavigationController + UIScrollView の組み合わせで使っている時に謎の余白ができる時

UINavigationController + UIScrollView の組み合わせで使っていて、UIScrollView 上に AutoLayout で上下左右0で View を設置しているのに、30px程度上にずれてしまうとき。

`navigationController.navigationBar.isTranslucent = false` にすると直るかもしれない。

ScrollView上のコンテンツとNavigationBarの重なっているところが透過していたら多分これで直せるはず。

通常のターゲットではちゃんと動いているのに、iOSSnapshotTestCase を用いたテストでだけこの対応が必要なのよくわからないけれど。。。

iOS

UITableView.RowAnimation の .none はアニメーションするよ

UITableView.RowAnimation の .none はアニメーションがnoneなわけじゃなく、デフォルトの設定を使うよという意味らしい。

The inserted or deleted rows use the default animations.

なのでアニメーションしちゃう。今更の気づき。

 

iOS
more