SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

ミニアプリを作って楽しく学ぶSwift

【作って学ぶSwiftアプリ開発入門】タイマー機能アプリ「カップラーメンタイマー」を作ろう!

ミニアプリを作って楽しく学ぶSwift入門 第6回

  • X ポスト
  • このエントリーをはてなブックマークに追加

STARTボタンを押すとタイマーを再セットする

 STARTボタンを押すとタイマーが開始するところまで実装ができましたが、実はSTARTボタンを押した後に再度STARTボタンを押すと残り時間のカウントダウンの数字が速いペースで減っていくようになってしまいます。

 これは二重にタイマーが実行されていることが原因で発生しています。なので、タイマーが開始した後にSTARTボタンを押した場合に再度タイマーが180から再セットされるように関数startTimerのコードを変更します。

func startTimer() {
    // ここを追加↓
    timer?.invalidate()
    remainingTime = 180
    //
    timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: { _ in
        remainingTime -= 1
        if remainingTime == 0 {
            timer?.invalidate()
            remainingTime = 180
        }
    })
}

 タイマーが0になった時の処理と同様に、タイマーを無効化して180の値を再セットしています。これでタイマーが開始した後に、STARTボタンを押しても再度180からカウントダウンできるようになりました。

繰り返し使用している処理を関数にする

 関数の説明でプログラム内で繰り返し使える処理をひとまとまりにできるとお伝えしました。この関数startTimerの中を見てみると重複したコードが確認できます。

func startTimer() {
    // 同じ処理
    timer?.invalidate()
    remainingTime = 180
    //
    timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: { _ in
        remainingTime -= 1
        if remainingTime == 0 {
            // 同じ処理
            timer?.invalidate()
            remainingTime = 180
           //
        }
    })
}

 この繰り返し使用しているコードを切り出した関数resetTimerを作成します。また、繰り返し同じコードを書いていた箇所をこの関数に置き換えます。

func startTimer() {
    // ここを追加↓
    resetTimer()
    timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: { _ in
        remainingTime -= 1
        if remainingTime == 0 {
            // ここを追加↓
            resetTimer()
        }
    })
}

// ここを追加↓
func resetTimer() {
    timer?.invalidate()
    remainingTime = 180
}

 コードは変わりましたが、アプリの動きに変化はないため、STARTボタンを何度押しても残り時間が再セットされることを確認できます。

残り時間を分かりやすい形式に変換する

 タイマーの機能はできましたが、アプリ上に表示されている180.000000という残り時間をもう少し分かりやすい形式に変換していきます。

 Swiftには分かりやすい形式に変換してくれるフォーマッターが用意されています。今回はその中から時間量を変換してくれるDateComponentsFormatterを使用します。まずは次のようにDateComponentsFormatterを追加してください。

struct CupRamenTimerView: View {
    @State private var timer: Timer?
    @State private var remainingTime: Double = 180
    
    // ここを追加↓
    let dateFormatter: DateComponentsFormatter = {
        let dateFormatter = DateComponentsFormatter()
        dateFormatter.unitsStyle = .short
        dateFormatter.allowedUnits = [.minute, .second]
        return dateFormatter
    }()

 まずは今回使用した定数の定義方法を説明します。

let 定数名: 型 = {
 //生成時に実行する処理
}()

 これは、定数を初期化する際に特定の処理を実行するための方法です。初期化時に一度だけ{}内の処理を実行し、その結果を定数として保持することができます。

 定数dateFormatterの初期化時に実行している処理は次の通りです。

  • DateComponentsFormatterを生成する
  • unitsStyleで変換する時間量の表示形式を短い形式になるように設定する
  • allowedUnitsで表示する単位を分と秒のみが表示されるように設定する

 これでフォーマッターの用意はできました。次にアプリ上に表示する文字をこのdataFormatterを使用して次のように変換します。

var body: some View {
        ZStack {
            Color.black
                .ignoresSafeArea()
            
            VStack(spacing: 24) {
                Text("3分間カップラーメンタイマー")
                    .font(.title3)
                    .bold()
                    .foregroundStyle(.white)
                
                // ここを変更↓
                Text("\(dateFormatter.string(from: remainingTime) ?? "180")")
                    .font(.system(size: 60))
                    .fontWeight(.black)
                    .foregroundStyle(.yellow)
                
                Button("START") {
                    startTimer()
                }
                .font(.largeTitle)
            }
        }
    }

 これでプレビューには3minと残り時間が表示されるようになりました。

 変更したコードの詳細を説明すると、Textの値として、dataFormatterに残り時間の値を渡して、フォーマットされた文字列を取得しています。ただ、関数dateFormatter.string(from:)の戻り値がString?Optionalになっているため、そのままではTextに反映することができません。??の記号を用いることで、値が空の場合に任意の値を設定することができます。

 以上でカップラーメンタイマーの完成です。

まとめと次回

 今回はアプリを作る過程で、ZStackを使って背景色をつける方法やif文や関数、Timerを使用する方法を学びました。

 今回は、3分間のみしか計測できないため、5分間を必要とするカップラーメンには対応していません。ぜひ、5分間のカップラーメンタイマー作成にもチャレンジしてみてください!

 もし、アプリのデザインについてもっと学びたいと感じはじめた方がいましたら、Apple Human Interface GuidelineでAppleのガイドラインを確認することをお勧めします。

 次回はアプリ「福笑いゲーム」を作ります。お楽しみに!

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
ミニアプリを作って楽しく学ぶSwift連載記事一覧

もっと読む

この記事の著者

リルオッサ(リルオッサ)

 ブレイクダンサー、時々iOSエンジニア。元ブレイクダンス世界2位。 現在は、楽しいことを追い求め、iOSアプリを作ったり、ビールを飲んだり、絵を書いたり、技術記事を書いたり、海外登壇チャレンジしたり、ブレイクダンスの大会を企画したりしています。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

CodeZine編集部(コードジンヘンシュウブ)

CodeZineは、株式会社翔泳社が運営するソフトウェア開発者向けのWebメディアです。「デベロッパーの成長と課題解決に貢献するメディア」をコンセプトに、現場で役立つ最新情報を日々お届けします。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/20803 2025/04/15 11:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング