Claude Codeを使って iOSアプリを開発する試みである。 すべてのプロンプトを履歴として載せる。
- Xcode 16.4
- Claude Code Proプラン
- 開発するアプリの相談を Claude でおこなった
- スクワットを題材にしたアプリで、MVP実装の簡単なものを想定。競合調査をおこない、アプリ名の精査もおこなってもらう
- 競合が多数おり、レッドオーシャンである分析をしてもらう
- Xcodeのプロジェクトをイチから作成するのは困難だと考え手動で作成。AIフレンドリーのため、フォルダー形式とする
- プロジェクトは現時点ではスケルトンである。README.md を読み込みアプリの仕様を理解せよ
- プロジェクトをビルドしてビルドが通ることを確認せよ。
- プロジェクトのテストを実行し、パスすることを確認せよ。
- CLAUDE.mdを日本語で作成せよ。
プロジェクトをもう一度読み取り、CLAUDE.mdを更新せよ。
HomeScreenを実装せよ。
ホーム画面の仕様:
- ナビバーの左上には設定ボタン
- ナビバーのタイトルにはアプリ名
- 画面には、過去のスクワットの記録を表示する (履歴機能)
- 履歴機能は別のタイミングで実装する。ここではモックで表示せよ
- 画面の右下にフロートボタンで、スクワットのスタートボタンを表示する
設定画面を実装せよ。
- ホーム画面から設定画面へ遷移する
スクワット画面を実装せよ。
- ホーム画面からスクワット画面へ遷移する
NavigationStack を利用して画面遷移して欲しい。
- ホーム画面から設定画面はpushで遷移
- ホーム画面からスクワット画面へはモーダルで遷移
CoreDataを使って、スクワットの記録を保存して欲しい
- スクワットの記録が存在しない場合は、ContentUnavailableView を使って、記録がない旨を伝えよ。
- ContentUnavailableView の actions にて、スクワットの記録を開始するボタンを実装し、ユーザーにスクワットをしてもらえるように誘導せよ
- スクワットの削除機能を実装せよ
- 設定画面の「1日の目標回数」の設定とスクワット画面のゴールの値を一致せよ
- 設定画面の「バイブレーション」の設定が有効になっている場合、スクワットを一回する度に小さな触覚フィードバック、目標達成すると大きな触覚フィードバックを実施して
- SquatWorkoutScreenViewModel を追加
- SquatWorkoutScreenViewModel#init で、UINotificationFeedbackGenerator() のインスタンスを作成
- バイブのたびに viewModel のメソッドを実行するようにして
- SquatWorkoutScreenViewModel を MainActor にして
- 設定画面でデータエクスポートをタップされたときに、データをエクスポートする機能を実装して
- データエクスポートの際にUIスレッドがロックされたような挙動となる。
- おそらくCoreDataからデータを読み出しcsvに変更しているときに操作がブロックされていると思われる。
- データエクスポートをタップしたら、画面を半透明で暗くして、データ生成中であることがわかるようにインジゲーターをぐるぐる回して欲しい。
- エクスポートデータができたら、インジゲーターを非表示にして、UIActivityViewController を表示させて
- 処理があまりにも早く終わってしまった場合インジゲーターが確認できない。
- 高速で終わる場合においても、最低2秒間はインジゲーターを表示してから、共有処理へ遷移して欲しい。
- 設定画面の全データ削除機能を実装せよ
- 削除しても良いかどうかの確認は2回確認すること。
- 2回目には「DELETE」とユーザーに入力させて、一致していれば全データの削除をおこなう
- データ削除されたあとに、ホーム画面が更新されておらず、記録が残ってしまっている。
- データの削除完了後に、削除したことをダイアログ表示して、ユーザーに伝えて欲しい
- データの削除確認ダイアログで、DELETE と入力せずに間違った値が入力された時、削除しなかったことをダイアログ表示して、ユーザーに伝えて欲しい
- SwiftUI の alert(:isPresented:actions:message:) は、iOS 26.0 で Deprecated になった。代わりに alert(:isPresented:presenting:actions:message:) を使って欲しい。
- SquatWorkoutScreen では NavigationView を使っている。NavigationView は Deprecated になっている。NavigationStack を利用せよ
git の e333030 〜 8f331ce までの変更点を確認して、変更点を要約せよ
現在のプロジェクトの内容に合わせて、README.md と CLAUDE.md を更新せよ。
追記:
- ここでlimitが発生
- ローカライズ対応をしたい。このアプリでは、英語、日本語、中国語、韓国語、ドイツ語、フランス語、ポルトガル語に対応したい。
- Viewで直接している文字列の使用をやめて、以下のようなヘルパーを使って対応して欲しい。
private enum LocalizedString {
static let cancel = String(localized: "cancel")
}
ローカライズファイルは、Localizable.xcstrings を利用すること。
- 設定画面の音声カウント機能を削除して
- リマインダー機能を実装せよ
- Info.plistのメッセージが消えてしまった。もう一度記入して欲しい。
- 設定画面の「プライバシーポリシー」をタップしたら、アプリ内ブラウザで以下のURLを開け
- 設定画面の「利用規約」をタップしたら、アプリ内ブラウザで以下のURLを開け
- スクワットの記録が存在しない場合は、ContentUnavailableView を使って実装せよ
- 設定画面のアプリバージョンの表示が 1.0.0 固定になってしまっている
- スクワットを開始すると View の横幅が急に狭くなってしまう。調整せよ
- アプリの趣旨にあったアプリアイコンを生成して、設定して
追記:
- ここでlimitが発生
- 設定画面では今後ウェブページへの遷移が増えるかもしれない。フラグで管理したくないので、以下のような構造体で状態管理するようにして欲しい。
struct Boo: Identifiable {
let url: URL
}
- SwiftFormat をSPMとして導入して、ビルドとテストの実行ごとにソースコードをreformatするようにBuild Phaseに設定を追加して欲しい
追記:
- ↑のプロンプトは全く機能せずに、よくわからないファイルを追加されるだけで終わってしまった。
- API Error: Claude's response exceeded the 32000 output token maximum. To configure this behavior, set the CLAUDE_CODE_MAX_OUTPUT_TOKENS environment variable. が発生した
追記:
- xcproj の操作はAIには難しそうだと判断して、手動で導入した。
ビルドが通るか確認せよ。通らない場合原因を調査せよ。
追記:
- 手動で追加したスクリプトを全部削除されてしまった。
- ENABLE_USER_SCRIPT_SANDBOXING の設定をNOにした
- スクワット画面の下のスタートボタンのサイズを半分くらいの大きさにして欲しい。
- スクワット画面で、スクワット開始後にナビゲーションバー上のキャンセルボタンをタップできる。
- ユーザーが意図した動作なのか? ユーザーに本当に閉じて良いのか確認をしたい
- ここはキャンセルではなく、閉じるボタンにしたい
- squatCount を SquatWorkoutScreenViewModel で管理するようにしたい。
- isVibrationEnabled の値も SquatWorkoutScreenViewModel にうまく渡したい
- 質問: onAppear で updateViewModelSettings() を呼び出し、AppStorageの値を設定しているが、SquatWorkoutScreenViewModel のコンストラクタに値を渡すことはできないのか?
追記:
- 以下の3つの点からできないとのこと。
- @AppStorageの値は、Viewの初期化時点ではまだ利用できない
- @StateObjectは、Viewの初期化時に一度だけ作成される
- @AppStorageの値が変更されても、ViewModelの初期化は再実行されない
- 進捗円のViewを Viewとして切り出して欲しい。
- ProgressCircleView をソースコードに切り出して欲しい。
- View フォルダーを作成して、そちらにファイルを作成せよ
- ProgressCircleView のサイズは、内部で指定せずに、利用する側のViewで frameを指定することはできないか?
- 質問:リセットボタンは必要か? 下にあるとユーザーが間違って押してしまうことはないか。閉じるボタンで代用できないか?
- リセットボタンを削除してください
- 一時停止ボタンと完了ボタンは、disable の場合に、ユーザーからみてわかりやすく押せないというのが伝わるように alpha を調整して欲しい
- ボタンが動いてしまうので、一時停止/再開ボタン は常に表示して、disable で管理して欲しい
- 一時停止してから再開すると経過時間がリセットされて0から始まってしまう。通算して計算するようにせよ
- 経過時間が進むと、Viewの横幅がガタガタに変わってしまう。フォントの種類を変更して欲しい
- UIFont.monospacedDigitSystemFont を使ってほしい
- 下部:コントロールボタン を カスタムViewとして外に切り出して欲しい
- ProgressCircleView でも同様に UIFont.monospacedDigitSystemFont を使ってほしい
- メインカウントボタン も カスタムViewとして外に切り出して欲しい
- MainCountButtonView のサイズは、内部で指定せずに、利用する側のViewで frameを指定できるようにせよ
- ビルド通した?
- 複数の画面・View で使う文字列については、LocalizedString に追加してもよい。
- しかし、特定の画面、特定のViewの場合は、 ファイルごとに
private extension LocalizedString
を置いて欲しい
- 質問:ユーザーにアクションを求める場合、alertが良いのか?それともactionSheetがよいのか?
回答:
- Alert(アラート)が適している場合:
- 重要な決定を求める場合
- データ損失の可能性がある操作
- 確認が必要な破壊的操作
- 選択肢が2-3個程度
- ActionSheet(アクションシート)が適している場合:
- 複数の選択肢から1つを選ぶ場合
- 破壊的でない一般的な操作
- 選択肢が3個以上ある場合
- コンテキストメニュー的な用途
- 本アプリで、変更すべき箇所がないかどうか確認して欲しい
回答:
- 現在の実装はiOS Human Interface Guidelinesに完全に準拠しており、変更不要です。特に設定画面の段階的削除確認システムは模範的な実装です。