0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Kiro を使って、iPhone 用の試験対策アプリを作りました。

0
Last updated at Posted at 2026-05-18

はじめに

こんにちは。
今回も Kiro を使った開発に関する内容です。

みなさん、AWS Certified Generative AI Developer - Professional(AIP-C01)受験していますか〜??
私は本試験の勉強用に、自分専用の学習アプリを作りました。開発には今回もKiroを使い、Spec駆動開発で要件定義からコード実装まで一気通貫で進めました。

私自身はiOSアプリの開発は全くの未経験でしたが、Kiroを使うことでほぼ半日(しかも大半はKiroが実行するタスク内のコマンド実行のTrust(信頼)をするかどうかの判定で止まるくらい)で手元のiPhoneで勉強を開始できました。

本記事では、Kiroを使った開発体験と、SwiftUI + MVVMで構築したアプリのアーキテクチャについて紹介します。

完成したアプリの概要

スクリーンショット 2026-05-17 20.39.32.png

項目 内容
対象試験 AWS Certified Generative AI Developer - Professional(AIP-C01)(*)
モード 練習(75問)/ 試験(75問・180分制限)/ 短時間(10問)
主な機能 四者択一問題、複数選択問題、解説表示、履歴管理、セッション中断・復元
技術スタック SwiftUI / Swift 6 / MVVM / UserDefaults / iOS 18+
動作環境 自分の iPhone15(iOS26)

(*)ただし、この問題内容については、差し替えができるので、AIP-C01に限ったものではないです。また、問題自体は、後述の通り、ChatGPTなどの生成AIに生成してもらったものを使っています。

そもそも公開を前提にしていないので、XCodeと自分のiPhoneをリンクさせて使っています。この範囲であれば、無料でiPhoneアプリを動かせますし、問題を取り込んでビルドするので、オフラインでも勉強を続けられます。

Kiroによる開発フロー

Spec駆動開発とは

すでにみなさんもご存知かと思いますが、Kiroでは「Spec」という仕組みで、以下の流れで開発を進めます。

要件定義(requirements.md)
  → 技術設計(design.md)
    → 実装タスク(tasks.md)
      → 自動実装

各フェーズでKiroが工程ごとの文書を生成し、ユーザーがレビュー・承認してから次に進みます。

実際の流れ

  1. 要件定義: 「iOS試験勉強アプリを作りたい」と伝えると、Kiroが10個の要件(ユーザーストーリー + 受け入れ基準)を生成
  2. 技術設計: MVVM構成、データモデル、プロトコル定義、正確性プロパティ(15個)を含む設計書を生成
  3. タスク生成: Wave(依存関係に基づく並列実行グループ)に分割された46タスクを生成
  4. 自動実装: タスクを順次実行し、ビルド確認まで自動で実施

アーキテクチャ

今回も、Kiroと、Claude Opusを使って実装を行いました。

全体構成

Sources/
├── Models/          # データモデル(Question, QuizSession, etc.)
├── Services/        # ビジネスロジック(QuestionEngine, SessionManager, etc.)
├── ViewModels/      # 画面状態管理(QuizSessionViewModel, etc.)
├── Views/           # SwiftUI View層
└── Data/            # 問題データ(Swift構造体として組み込み)

主要コンポーネント

コンポーネント 責務
QuestionEngine 問題のバリデーション、ランダム選出、選択肢シャッフル、正誤判定
SessionManager セッションのライフサイクル管理(生成・中断保存・復元・完了)
ScoreCalculator 正答率の計算
HistoryStore UserDefaultsによる履歴の永続化(モード別最新10件)
TimerManager 試験モード用カウントダウンタイマー

プロトコル設計

テスタビリティのため、全サービスをプロトコルで抽象化しています:

protocol QuestionEngineProtocol {
    func selectQuestions(count: Int) -> [Question]
    func judgeSingleChoice(question: Question, selectedIndex: Int) -> JudgmentResult
    func judgeMultiChoice(question: Question, selectedIndices: Set<Int>) -> JudgmentResult
    func loadValidQuestions() -> [Question]
}

技術的なポイント

1. 選択肢のシャッフル

何度も解くうちに「3番目が正解」と位置で覚えてしまう問題を防ぐため、出題時に選択肢の順番をシャッフルし、正解インデックスも追従させています。

private func shuffleChoices(_ question: Question) -> Question {
    let shuffledIndices = Array(0..<question.choices.count).shuffled()
    let newChoices = shuffledIndices.map { question.choices[$0] }
    
    var newCorrectIndices = Set<Int>()
    for oldIndex in question.correctIndices {
        if let newIndex = shuffledIndices.firstIndex(of: oldIndex) {
            newCorrectIndices.insert(newIndex)
        }
    }
    
    return Question(
        id: question.id,
        text: question.text,
        choices: newChoices,
        correctIndices: newCorrectIndices,
        type: question.type,
        explanation: question.explanation
    )
}

2. テキストデータからの問題変換

問題データはChatGPTなどの生成AIに作ってもらった問題を元にPythonスクリプトでパースし、Swift構造体に変換しています。

対応する入力形式:

問題1

企業はAmazon Bedrockを使用して...

A. 選択肢A
B. 選択肢B
C. 選択肢C
D. 選択肢D

正解: B
解説: Bedrcok Guardrailsは...

このあたりは Kiro がいい感じにパースをしてくれるので問題の範囲(問題文、選択肢、答え、解説)がわかるようになっていればOK。

3. @ Observable + @ MainActor

Swift 6のObservationフレームワークを使い、ViewModelを @Observable で定義。@MainActor でUI更新のスレッド安全性を保証しています:

@MainActor
@Observable
public final class QuizSessionViewModel {
    public var selectedIndices: Set<Int> = []
    public var isResultShowing: Bool = false
    // ...
}

4. 結果表示中の操作ロック

回答確定後に選択肢を変更できないよう、isResultShowing フラグでガードしています:

public func selectChoice(at index: Int) {
    guard !isResultShowing else { return }
    // ...
}

5. セッション中断・復元

@Environment(\.scenePhase) でアプリのライフサイクルを監視し、バックグラウンド移行時に自動保存:

.onChange(of: scenePhase) { _, newPhase in
    if newPhase == .background || newPhase == .inactive {
        if quizViewModel.session.state == .inProgress {
            quizViewModel.suspendSession()
        }
    }
}

成果物の画面の雰囲気

四者択一問題:
スクリーンショット 2026-05-17 20.39.54.png

複数選択問題(回答):
スクリーンショット 2026-05-17 20.40.27.png

結果画面;
スクリーンショット 2026-05-17 20.41.03.png

非常にシンプルですが、レスポンスよく動きます。アイデアが出れば機能追加して自分好みのアプリに育てることも可能。
結果画面は円グラフを表示したり、正解数を、分数で表示してもよいかなと考えているところです。

Kiroを使った所感

良かった点

いつも通りの感想にはなってしまいますが。

  • 要件定義から実装まで一貫した流れで進められる。手戻りが少ない
    • これに関しては、作りたいもののアイデアがあれば、サクッと形にできて、さらにVive Codingよりもしっかりしたものを作れるのがよいですね。あとから機能追加をしたいとか、修正したいといったときにも柔軟に対応が可能
  • プロパティベーステストの設計まで含めた設計書を自動生成してくれる
  • 並列タスク実行で、独立したコンポーネントを同時に実装できる
  • テキストデータの変換など、雑務的な作業も対話的に依頼できる

注意点

  • Xcode固有の設定(Bundle ID、署名、デバイス信頼)はKiroだけでは完結しない
  • 生成されたコードは動くが、UIの細かい調整(スクロール位置のリセットなど)は実機やXCodeのiPhoneシミュレータでの動作確認後にフィードバックが必要

問題データの追加方法

テキストファイルを用意して、Kiroに「このファイルを読み込んで」と伝えるだけで変換・組み込みまでやってくれます。
前述のように、ChatGPTなどで問題を生成し、Markdown形式で出力してもらうのも有効です。ただ、うちのChatGPTでは、何度行ってもMarkdown形式で出力してくれませんでした。

まとめ

Kiroを使うことで、iOS開発の経験が浅くても、Spec駆動で設計から実装まで効率的に進められました。特に試験勉強のような「自分だけのツール」を素早く作りたい場面では、AIアシスタントとの対話的な開発が非常に有効だと感じました。
自分だけのアプリってよいですよね。アイデアをサクッと形にできる、Kiroはなくてはならない素晴らしいパートナーですね。


記載されている会社名、製品名、サービス名、ロゴ等は各社の商標または登録商標です。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?