App Storeが承認した
2週間前,私はブログに「まだ開発中。まだ完成していない」と書いた。今日,DIALØGUE(ダイアログ)はApp Storeで公開されている。最後の40%が実際どんな作業だったか,正直に話す。
2週間前,ブログの締めにこう書いた。「まだ開発中。まだ完成していない。娘に何を話せばいいか,まだわからない。」
App Storeに公開できたら続報を書くと約束した。審査落ちしたときも書く,と。「リジェクトされた話の方が面白いかもしれない」とも書いた。
DIALØGUE(ダイアログ) - AI Podcast Studio がApp Storeで公開された。 Swiftを一度も書いたことのない人間がClaude Codeで作った,ネイティブSwiftUI iOSアプリだ。トピックを入れるかPDFを渡すだけで,ポッドキャストエピソードがまるごと生成される。今すぐダウンロードできる。
ただし,一発で通ったわけではない。正直に言うと,リジェクトの話の方が面白いだろうと思っていた。その予感は当たっていた。
最初のリジェクト——何が起きたか
最初の申請はリジェクトされた。ガイドライン2.1 — パフォーマンス:アプリの完成度。アプリ内購入が壊れていた。
Appleからのレビューメッセージは丁寧だった。初めての申請だと気づいてデベロッパープログラムへの参加を祝福してくれた上で,問題を明確に説明してくれた。レビュアーが購入しようとしたら,IAPプロダクトがエラーを返したのだ。
ここが厄介なところで,購入フローは私のテストでは完璧に動いていた。問題はAppleのサンドボックス環境——開発環境とも本番環境とも違う,あの独特な環境——にあった。StoreKitの設定はApp Store Connectと完全に同期していないといけない。私のはしていなかった。ローカルのStoreKit設定ファイルでテストしていたけれど,レビュアーが叩いていたのは本物のサンドボックスだった。
同日中に修正して再申請したら,通った。その後すぐにv1.0.1のバグ修正も出したが,こちらもすんなり通過した。
申請は合計3回。リジェクト1回。そのリジェクトから,2回の承認より多くのことを学んだ。よくあるパターンだと思う。失敗はいつも,成功より多くを教えてくれる。
「最後の40%」の正体
元の記事で,AIが60%まで連れて行ってくれて,残りの40%は完全に人間の仕事だと書いた。今ならもう少し具体的に言える。gitログが証拠だ。
16コミット。57ファイル変更。4,886行追加。 Swiftファイルは69本から88本に,コード行数は7,568行から11,459行になった。約4,000行分の「磨き上げ」。
その16コミットに何が入っていたか,ざっくり時系列で振り返る。
初日から必要だったテストスイート
最初のスキャフォールドにテストはゼロだった。ゼロ。Claudeは69ファイルのプロダクションコードを生成して,テストは1本も書いていなかった。元の記事を書いた直後,最初の本格的なコミットでユニットテスト176本とインテグレーションテスト19本を追加した。ローカルのSupabaseインスタンスに対して動くやつだ。
書いた途端にバグが出てきた。存在しないデータベースカラムによるShowモデルのデコード失敗,トラック終了時にAudioPlayerがリセットされない問題,ライブラリのリロード競合,作成ウィザードのnil UUIDガード漏れ。どれもそのまま本番に出ていたらクラッシュしていた。
これは名前をつけておく価値のあるパターンだと思う。AIはテストインフラなしでコードを生成する。 テストが書けないわけじゃない——頼めばClaudeはちゃんと書く。でも最初のプロンプトはいつも「アプリを作って」で,「テスト込みでアプリを作って」じゃない。テストを書いたのは,テストなしでは出荷できないと自分で判断したからだ。
Studio——スタブから本物へ
もともとの「Studio」機能(定期配信番組の管理)は,ほぼプレースホルダーだった。2コミット後には本物のプロダクトになっていた。テンプレートグリッドで番組作成,ステータスバッジとアクションボタン付きのエピソード管理,編集・削除のワークフロー,タイムゾーンピッカー付きスケジュール設定,ボイスカスタマイズシート。
さらにStudio Phase 2で,番組詳細画面のリデザイン,エピソードごとのリトライ・削除,クレジット残高チェック付きの手動エピソード生成を追加。動作確認用にXCUITestも8本書いた。
これが「AIはコードベースを作ったけど,プロダクトは作っていない」の具体例だ。Studioはコンパイルが通っていた。画面も表示された。でも実際にポッドキャストの定期番組を管理することは,できなかった。
オーディオプレイヤーを再発明
元の記事でミニプレイヤーを削除したと書いた。あれは間違いだった。結局もっと良いミニプレイヤーを作ることになった。最終デザインは,タブバーの上に常駐するミニプレイヤーバー。進捗表示,スキップ,再生・一時停止。タップすると「Now Playing」シートが開き,シークスライダー,速度セレクター(0.5x〜2x),トランスポートコントロール,サウンドリングのアニメーションが出てくる。
厄介だったのはisSeekingの状態管理だ。これがないと,スライダーの位置とオーディオオブザーバーが喧嘩してガタガタになる。たった1行のstate変数なのに,原因特定に1時間かかった。
オフラインダウンロードも追加した。ライブラリでダウンロード済みエピソードに緑アイコン,完了時のトースト通知,Now Playingに「Downloaded」ラベル,スワイプでダウンロード削除。DownloadManagerのURLSessionデリゲートに一時ファイルの競合があり,何も言わずに失敗していた。コールバック内で同期的にファイルを移動することで解決。コードレビューでは絶対に見つからないタイプのバグだ。
セキュリティ強化——全レイヤー
これは正直,背筋が冷える作業だった。iOSアプリだけでなくスタック全体のセキュリティ監査をしたら,複数レイヤーに脆弱性が見つかった。権限が過剰なデータベース関数,認証のエッジケース,トークン検証の穴,バックエンド各所での入力バリデーション不足。
どれもiOSのSwiftコードの中にはなかった。iOSアプリが通信するバックエンド側だ。でも,iOSアプリを出荷するということは,スタック全体がユーザーのポケットに入るということ。その事実が,すべての要求水準を引き上げた。ウェブアプリとして「問題なく動いていた」コードが,Appleの審査を通って人々が持ち歩くアプリに載ると思うと,もう許容できなかった。
StoreKit——リジェクトの元凶
StoreKitのサンドボックステストは別世界で,まさにこれが最初のリジェクトの原因だった。 サンドボックス環境は本番と挙動が違う。トランザクションが永遠に「pending」のまま止まることがある。XcodeのStoreKit設定ファイルは手動同期が必要。コードでは完璧に動く購入フローがサンドボックスで無言で失敗する原因を一晩かけて調べたら,App Store ConnectのプロダクトIDに末尾スペースが1つ入っていた。たった1文字。
Appleのレビュアーがサンドボックスエラーに当たったのは,StoreKit設定がApp Store Connectと同期していなかったからだ。ローカルでは完璧に動いていた。でもレビュアーが使っていたのは私のローカル設定ファイルではなく,本物のサンドボックスだ。同日中に修正したけれど,「自分のマシンでは動く」と「Appleの環境でも動く」の間にある溝は,想像以上に深い。
購入検証のチェーンはそれだけで1つのプロジェクトだった。iOSアプリがトランザクションのJWS(JSON Web Signature)をサーバーサイド関数に送り,Appleの署名済みレシートを暗号チェーンごと検証する。デコードだけじゃなく,署名の実検証だ。正しく動くまでに2コミット費やした。
プライバシーとApp Storeコンプライアンス
プライバシーとコンプライアンスは,法的責任を伴うフォームと判断とチェックボックスの山で,AIに代わりに埋めてもらうことはできない。 App Tracking Transparencyの申告,プライバシー「栄養表示」ラベル,暗号化の輸出コンプライアンス(HTTPSも対象だ),コンテンツの権利,Turnstile CAPTCHA統合。Claude CodeはSwiftを書けるけれど,自分のデータ収集が「Data Used to Track You」ラベルに該当するかどうかは判断してくれない。
MFAの完全実装と7言語対応
最初のMFA実装は壊れたスタブだった。ファクターIDが空で,検証だけのフロー。これを完全なTOTPライフサイクルに書き直した。登録,QRコードスキャン(ネイティブCoreImage生成),検証,ステータス確認,無効化。以前は存在しなかった394行のMFAView.swiftだ。
7言語のローカライズ——英語・スペイン語・フランス語・日本語・韓国語・ベトナム語・中国語で253のUI文字列を翻訳した。Claudeが担当して,出来はおおむね良かった。ただ,日本語での「おおむね良い」は,文法は合っているのにどこかロボットっぽいボタンラベルが混ざっている,という意味だ。スマホの言語設定を切り替えて実際にアプリを使ってみて,そういう箇所をいくつか潰した。これはAIにはまだできないテストだと思う。
DIALØGUEで何ができるか
元のビルドストーリーを読んでいない方のために,DIALØGUEが何をするアプリかまとめておく。
トピックを入力するかPDFをアップロードすると,リサーチ済み・スクリプト済み・音声付きのポッドキャストエピソードが生成される。2人のAIホストがトピックについて自然に会話する。実際のリサーチに裏付けられた対話だ。マイクは要らない。
iOSアプリの機能:
- 5ステップの作成ウィザード — トピック,フォーマット,カスタマイズ,アウトラインレビュー,スクリプトレビュー
- 7言語30種類のAIボイス — 英語・スペイン語・フランス語・日本語・韓国語・ベトナム語・中国語
- 9種類のポッドキャスト形式 — Tech News AnalysisからInvestigative Comedyまで
- ロック画面コントロール付きオーディオ再生 — バックグラウンド再生もそのまま動く
- Apple Sign-In,Google OAuth,メール認証
- アプリ内購入 — サブスクリプションなし,クレジット制:4クレジット$4.99,9クレジット$9.99,18クレジット$19.99
- Studio — 自動的に新しいエピソードを生成する定期番組の設定
- PDFアップロード — 研究論文,レポート,書籍をソース素材として使用可能
正真正銘のネイティブSwiftUIアプリだ。ウェブラッパーでもReact Nativeでもない。69本のSwiftファイルから始まって,今は88ファイル・11,459行,195本のテスト付き。これを出荷できたことを,心から誇りに思う。
「磨き上げフェーズ」の見積もり,どれだけ外れたか
「アプリはまだ開発中で,最終的な磨き上げフェーズにある」と書いた。技術的には正しかった。でも「磨き上げ」の大部分が実は新規開発だったことを甘く見ていた。
gitログを今見返すと,16コミットは「磨き上げ」じゃない。開発の第2フェーズだ。テストスイートだけで——ユニットテスト176本,インテグレーションテスト19本——1つのプロジェクトだった。Studioはスタブから完成形に化けた。オーディオプレイヤーは2度作り直した。セキュリティ強化は40以上のバックエンド関数に手を入れた。MFAはゼロから書き直し。
ミニプレイヤーを削除した件も,間違いだった。結局はNow Playingシート,スピードコントロール,ダウンロードインジケーターを備えた,より良いものを作った。「削除する」という判断自体は正しかった——最初のミニプレイヤーは出来が悪かった。でもコンセプトは正しかった。ちゃんと作り直す必要があっただけだ。
全体像が見えた今の正直な内訳は,こうだと思う。AIが基盤を作る(60%),人間がプロダクトを作る(30%),App Store申請プロセスが残りの10%を教えてくれる。
EUでは使える?
DIALØGUEは全世界で提供中だが,EU向けはAppleが審査中。 EUのデジタル市場法(DMA)で追加のコンプライアンス手続きが求められる。代替決済手段の開示,プライバシー関連の書類,事業者登録の詳細。書類はすべて出した。Appleのレビュー待ちだ。近くEU各国でも使えるようになるはず。
EU在住で待てない方は,ウェブアプリが同じ機能をどこからでも使える。
AI支援のiOS開発,どれだけ速い?
DIALØGUE iOSアプリは最初のコミットからApp Store承認まで約2週間。AIのスキャフォールディングに1夜,人間のプロダクト作業に2週間。 この表はずっと更新し続けているけれど,毎回何かを教えてくれる。
| プロジェクト | 複雑さ | 開発期間 |
|---|---|---|
| DIALØGUE v1 | MVPポッドキャストジェネレーター | 約6ヶ月 |
| STRAŦUM | AIエージェント10体,フレームワーク11種,マルチテナント | 75日 |
| サイトリデザイン | WordPressフロントエンドの刷新 | 3日 |
| DIALØGUE v2 | ウェブアプリの完全リビルド | 14日 |
| ブログ移行 | WordPress → Next.js,490記事,Sydney RAG | 4日 |
| DIALØGUE iOS | ネイティブiOSアプリ,Swift初体験 | 約2週間(スキャフォールド:1夜) |
DIALØGUE iOSのスキャフォールドから出荷までは約2週間。スキャフォールド自体は1夜。この比率——AI作業1夜,人間の作業2週間——が,AI支援開発の現在地をすべて物語っている。
AIの部分はどんどん速くなる。人間の部分はほぼ変わらない。2週間前にそう書いたけれど,今も同じだ。
AIがコードを書く時代に必要なスキル
元の記事では,まだ正しいアドバイスを探している最中だった。「シミュレーターを起動する側の人間になれ」が,あのとき出せた精一杯だった。
実際に出荷してみた今なら,もう少し具体的に言えると思う。
このアプリが存在するのは,AIにはできなかった3つのことがあったからだ。
-
プロダクトを使った。 テストじゃなく,使った。ポッドキャストを作って,通勤中に聴いた。アウトラインレビュー画面にリサーチのソースを出すべきだと気づいたのは,自分が「この事実の出どころはどこだ?」と知りたくなったからだ。
-
正解のない判断を下した。 ミニプレイヤーは残すか消すか。作成ウィザードのカスタマイズはどこまでが「やりすぎ」か。Studioはタブにするかセクションにするか。これはエンジニアリングの問題じゃない。センスの問題だ。センスは,たくさんのプロダクトを——良いものも酷いものも——使い込んで,「これが正しい」という直感を育てることでしか身につかない。
-
人間のために設計されたシステムを渡り歩いた。 App Store Connect,プライバシー申告,輸出コンプライアンス,スクリーンショット要件——どれも自動化できない。読んで,文脈を理解して,法的・ビジネス的な判断を下す必要がある。複雑な人間のシステムを渡り歩く力は,なくならない。
だから更新版のアドバイスは,こうかもしれない。物事を深く使い込む習慣をつけること。品質にこだわることでセンスを磨くこと。シンプルに設計されていないシステムに慣れること。
「批判的に考えろ」より具体的だし,真実に近いと思う。それで十分かどうかは,まだわからないけれど。
ダウンロード
アプリは無料。アプリ内でクレジットを買う形式で,サブスクリプションはない。
世界中で提供中。EUでの提供はAppleが処理中で,間もなく利用可能になる予定。ウェブアプリはどこからでも使える。
よくある質問
DIALØGUEはApp Storeにありますか?
ある。DIALØGUE - AI Podcast Studio は2026年3月にApp Storeで公開された。無料ダウンロード,アプリ内クレジット購入制(4クレジット$4.99,9クレジット$9.99,18クレジット$19.99)。全世界で提供中。EU向けは申請済みで,Apple側の処理待ち。
EUでは?
申請済みで,Appleが処理中。EUのデジタル市場法(DMA)で追加手続きが求められるが,書類はすべて出した。Apple側のレビュー待ちで,近く利用可能になるはず。それまではウェブアプリがEUを含むどこからでも使える。
Appleにリジェクトされた?
された。最初の申請はアプリ内購入の不具合(ガイドライン2.1:アプリの完成度)でリジェクト。StoreKitのサンドボックス設定がApp Store Connectと同期しておらず,審査中に購入がエラーになった。同日中に直して再申請したら通った。その後v1.0.1も通過。合計3回申請,リジェクト1回。そのリジェクトの方が,どちらの承認より多くを教えてくれた。
どのくらいかかった?
元のブログ記事からApp Store承認まで約2週間。Claude Codeが1夜で69本のSwiftファイルをスキャフォールド。残りの16コミットで57ファイルに4,886行追加——テスト,Studio機能,オーディオプレイヤーの再設計,MFA書き直し,セキュリティ強化,StoreKit検証,ローカライズ,そしてApp Store申請プロセス。出荷時は88ファイル・11,459行・テスト195本。
最後の40%で一番大変だったことは?
StoreKitのサンドボックステスト。「コードでは動く」と「Appleのトランザクションシステムで動く」のギャップは想像以上に大きい。サンドボックスのトランザクションは本番と挙動が違い,プロダクトIDは末尾スペース1つまで完全一致が必要で,フィードバックのループが遅い。ユニットテストのようにサクッと確認できない。
ウェブアプリはまだ使える?
もちろん。podcast.chandlernguyen.com は同じ機能で,どのデバイスでも動く。iOSアプリにはApple Sign-In,ロック画面コントロール,オフラインダウンロードといったネイティブの利点があるけれど,ポッドキャスト生成のコア体験はまったく同じだ。
娘に何を話せばいいか,まだ考えている。でも少なくとも今は,「人間の仕事こそが難しいんだよ」と言うとき,指差せるアプリがある。
それでは,Chandler








