swiftでタイマー処理がしたい [swift1.2]
昨日投稿したXCTestの記事が割とアクセスされていてびっくりしています。こんにちは。
〜Tests.swiftって何?XCTestでの単体テストのススメ [swift1.2] - MILLEN BOX
今日はタイマー処理をテーマにしたいと思います。
高橋名人もびっくりの連打アプリを作成しました。10秒間の間に何回ボタンをタップできるかを競います。
尚、本アプリはテストアプリですので、もう一度プレイしたければ再度ビルド実行お願いします!
テストアプリのGithubは以下です。
10秒という時間を計るにはswiftではどうすればいいのでしょう?
その仕組みは以下のようになります。
自分ポイント1
残念ながら10秒たったら状態を変更するような機能はswiftには存在しません。
しかし「決められた時間毎に教えてくれる」機能は持っています。
決められた時間は今回の場合は1秒です。(減っていく時間を表示したいから)
まず1秒毎に実行したい関数を作成します。
以下の updateTimer() が1秒毎に実行されれば、関数内でcountupTimerがインクリメントされることによってタイマー開始から現在までの秒数がわかります。
import UIKit class ViewController: UIViewController { ... /** タイマー関数。1秒毎に呼び出される。 */ func updateTimer() { println("\(__FUNCTION__) is called") countupTimer++ //countupTimerをインクリメント let countdownTimer = editTimerCount(countupTimer) //カウントアップ表記をカウントダウン表記へ変換 updateTimerLabel(countdownTimer) //タイマー表示ラベルをアップデート if countdownTimer <= 0 { timerState = false startState = false countupTimer = 0 timer.invalidate() } println("\(countupTimer)") } }
自分ポイント2
1秒毎に updateTimer() を実行するにはどのようにすればいいでしょうか。
NStimerクラスの変数(正確にはインスタンス)を作成し、そいつにNSTimer.scheduledTimerWithTimeInterval
を放り込むと決められた時間毎にお知らせしてくれるタイマーがスタートします。
NSTimer.scheduledTimerWithTimeInterval
呼び出し時の引数によってタイマーの時間、その際に呼び出される関数が変更されます。
今回は (1, target: self, selector: Selector("updateTimer"), userInfo: nil, repeats: true)
となります。
第1引数がタイマーの秒数、第3引数 selectorが呼び出される関数です。
自分ポイント3
10秒たったらタイマーの実行を中止したいです。
そのような時には中止したい箇所で timer.invalidate()
を実行しましょう。
class ViewController: UIViewController { @IBOutlet var counterDigit: [UILabel]! @IBOutlet var decimalPlace: [UILabel]! var countPushing = 0 var countupTimer = 0 var timer = NSTimer() //NSTimerのインスタンス作成 var timerState = false var startState = true .... @IBAction func buttonA(sender: AnyObject) { pressButtonFunc() } @IBAction func buttonB(sender: AnyObject) { pressButtonFunc() } /** ボタンA及びBを押した時に実行する関数 */ func pressButtonFunc() { //println("\(__FUNCTION__) is called") //timerStateがfalseの時にはTimerをスタート。trueの時には無視する。 if timerState == false && startState { timerState = true timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("updateTimer"), userInfo: nil, repeats: true) //タイマーを作成!!! } if timerState && startState { countPushing++ //countPushingをインクリメント let countAfterEdit = editCount(countPushing, digitNum: counterDigit.count) //カウントを表示用にEdit updateCounter(countAfterEdit) //カウンタをアップデートする } } /** タイマー関数。1秒毎に呼び出される。 */ func updateTimer() { println("\(__FUNCTION__) is called") countupTimer++ //countupTimerをインクリメント let countdownTimer = editTimerCount(countupTimer) //カウントアップ表記をカウントダウン表記へ変換 updateTimerLabel(countdownTimer) //タイマー表示ラベルをアップデート if countdownTimer <= 0 { timerState = false startState = false countupTimer = 0 timer.invalidate() } println("\(countupTimer)") } }
アプリとしては色々課題がありますが、タイマー処理を持ったアプリが完成しました。
時間制限を持ったゲームなどを作成する場合には必須なのではないでしょうか。