[わ]

AIと一緒にTALES iOSアプリを開発した

おはようございます。waturaです。TALES しっていますか?ゲームじゃないです。きつねみたいなキャラでもないです。noteの小説投稿サイトです。

小説が無料で読める物語投稿サイト TALES(テイルズ) ここでは、誰でも、自身が創作した物語を投稿することができます。誰でも、投稿された物語を読み、楽しむことができます。そんな、 tales.note.com

4月ごろにWeb版TALESはリリースされたのですが、ついに、iOS/Android版もリリースしました。

アプリ自体のリリース内容とか公式情報は下記記事から参照してください。

TALESアプリはWeb版が爆速開発されているところを影から眺めるところから開発が始まりました。開発はやいねーというのを横目でみながら、アプリチームは少数精鋭で開発をすすめていきました。


この記事は、noteのみんな Advent Calendar 2025 の15日目の記事です。
もともと、アドベントカレンダー関係なしで公開しようと思っていたのですが,そのうちーと思っている間にこの季節まで放置してしまったので、アドベントカレンダーとして公開しました。
下書きを書いた時点から差分が発生していたので、記事最後の方に**「公開前から追記」**として12月時点での感想も追加しています。

adventar.org


iOS版の結構な範囲でCursorやClaude Codeをがっつりつかってつくりました。一時期、Claude Codeがcommitterに表示される状態のまま実装してしまっていたのですが,トップをぶっちぎるみたいな感じになっていました。

で、どうだったのか。

おおむね日進月歩でAIはカイゼンされていたようにおもいます。たまに、アホのAIが混じっていたり、Claude 3.5とかの時代のコードが4.0のものより微妙だったりということが、あったりしました。ちょこちょこ記事をかいていたように、WindSurfとかZedとかにも手を出したりしつつ、CursorでもClaude Codeでも、Sonnetを中心に使っていました。
また、Perplexityで検索したりとか、Claude側でチャットしてコードを考えたりとかもしていました。

ここがめんどうだった

だいたい、このあたりがイラっとしながらリテイク祭をしたり、俺が書いたほうが早い!って書き直していたところになります。

ObservableObjectがスキ

ルールに、@Observable つかえよ!ってかいているのに、ObservableObjectをつかってPublishedをめっちゃ書くコードみたいなのを量産してくることがありました。だいたい、Observableつかって!って指示すると修正してくれました。

Environmentがエラーじゃないのにエラー

AIじゃなくて、Sourcekit LSPかSourcekit側の問題だと思うのですが、別ターゲットでつくられた、ObservableをあてられたclassをEnvironmentにしているとエラーが帰ってきていました。

「まずは、Observableのエラーを修正します。」とかいいながら、救いのない修正ルートにはいっていき、猛烈にグダグダになっていく。みたいなことを以前はよく行なっていました。

エラー無視してという指示を与えて回避していました。

Concurrency わからん

私も最適なコードがわからないので、二人してわからん。こうか?ああか?と試したりした結果、あきらめて @unchecked Sendableとかで逃げるみたいなことがよく発生していました。

iOS 26は存在していません

空想バージョンですね!とかいわれた時は超絶イラっとしました。まあ、仕方はないのですけども。。。

こっちの方がモダンでいいコードだよ

結局できなくて諦めたのですが、TabBarのアイコンに小さな赤丸バッジをつけたい。という要望がありました。UIKitなら難なくできることなのですが、SwiftUIだとでっかい赤丸バッジは簡単ですが、小さな赤丸はかなり厳しい感じでした。
そもそも、アイコンに色をいれることすら面倒な感じでした。結局、Graphics Contextをつかって直接赤丸を描くとかしたら、やりたいことがある程度できました。が、ダークモード対応とかでコードがカオスになったりしたので諦めました。
この試行錯誤をしているときにAIにきくと、overlayつかった方がいいよ!SwiftUIのXXXをつかったモダンな書き方にしておきました。とかって書き換えてくれるというのを何度も、何度もやられました。

スキじゃないよ。いいねだよ

Like apiをたたいたりするボタンがあると、しれっと、「スキ」から「いいね」書き換えてくれていたりしました。
ルールに用語集をつくっていれておいたら、やりたい放題文言を変えるのをやめてくれました。
また、用語とか文言という点で関連するイラッとポイントなのですが、勝手に翻訳を変えてくるというイラッとポイントもありました。英語キーが指定されているときに,処理ごとに日本語文言を変えて無駄に差分をつくってくるみたいなことをやられたりしました。
キー自体を日本語で入力し、日本語の翻訳はそのまま日本語キーのままにするという指示を与えることで回避しました。

英語化するときは、ちゃんと用語集をつくる必要があるんだろうねと思いました。

というわけで、そうじゃないやめろって何度も、いいながらも効率よくAIたちががんばって開発を進めてくれました。

勝手にコミットするなっていっただろ

ルールにも書いているし、commitを行なうcommandにも指示されたタイミング以外で追加のコミットをするなということを書いているんですが無視されます。
コミットするし、勝手にpushもします。うごかないコードでも気にせずやってくれるので、すごく困ります。
compactされたあととかは、瑣末なルールダという判断をされているのか、ほぼ確実に無視されています。かなしいです。

これは人間ががんばったほうが早い

しかし、まあ、人間がやったほうが早いこともいろいろあります。

このあたりは明確に、人間がやったほうがまだはやいです。
ボタンの文言を一つだけ変更するのとかは、AIにはできないといってもいいような修正になります。
類似の文言も一緒に変更しちゃうし、いろいろ探してくるので地味に時間もかかります。
レイアウトとかも人間がちょちょっと順番をかえるとか、VとHかえるとかをした方が早いです。
ただし、おおまかで正しくはないレイアウトを組んでもらうところとかは、すごく早いので、ざっくりやってもらった後修正するというながれが多かったです。

言語化がたりなくて、**明確な指示ができない==ただしくないコードが実装される。**なので、俺が自分でつくる!ってしたときの方がはやいパターンもありました。
そういったパターンでも適当な疑似Swiftコードを書いて、その流れでつくってくれ。これがもともとのあいまいな指示だよ!と渡すといい感じに完成させてくれることもありました。

その他

開発はClaude Codeが中心となっているブランチが複数と私が中心となるブランチといった感じで,複数ブランチを並行して動かしているときが多かったです。その際,ほぼ必須だったのがGit Worktree なのですが、そのままつかっていると、キャッシュの衝突とかで崩壊することがありました。
なので、Xcode側でDerived Dataの場所をRelativeに変更し、それぞれのブランチでDerived Dataを管理するようにしました。
そうすると、初回はめっちゃ重いのですがその後はかなり安定して並列で動かせるようになりました。

あとは、並行開発の数だけ、仮想デスクトップを用意し、Xcode、Terminal、Cursor、iOS Simulatorをならべておくという運用をしていました。もともとはTerminalのタブとか画面分割を多用する人だったのですが、それぞれの仮想デスクトップにTerminalウィンドウがいるほうが幸せだと気がつき、ウィンドウを量産していました。
ブランチを切り替えるときはウィンドウを閉じて,新しく開き直す用にしていました。

まとめ

おまえ人のはなしきけよ!さっきそれいったよね?ってなることも多々あるものの、AIをつかった開発はiOSアプリ開発においても、かなり有効に作用していたと思います。
もう、私はClaude CodeとかのAgentと一緒じゃないと開発できない体になってしまいました。


公開前から追記

実はこの記事自体は、アプリをリリースした9月ごろに下書きをおおむね書いていました。ただ、なんでか、公開するのを忘れてアドベントカレンダーにいれることにしたんですが、すでに、記事が陳腐化していました。

この3ヶ月の間にLLMたちの性能が爆上がりしていったことにより、「ここがめんどうだった」に書いた項目のほとんどをもうみることがなくなりました。今も引き続き悩んでいるのは、勝手にコミットしつづける問題です。ぜんぜん話を聴いてくれないので悲しくなります。

手動でやったほうが速いよ。と書いたところとかもカイゼンされており、かなり、AIに丸投げ出来るようになってきました。
**もう、私はClaude CodeとかのAgentと一緒じゃないと開発できない体になってしまいました。**もう、9割くらいはAIがコードをかいています。もっとかもしれません。

今のAIとならばもっと短期間で開発できたかもしれません。そして、来年のAIとならば、俺、いらないんじゃない?ってなりながら開発できたかもしれません。

Xcodeでキャッシュ衝突疑惑も解消しているようで、同じ場所に保存するようにしても、問題なくうごいていそうでした。
無限にキャッシュがでかくなる問題はあるのですが。。。

おまけ

毎日のようにたたいている、コミットコマンドとPR作成コマンドです。

1. If current branch is main, make new branch
2. commit with Conventional Commits

Write text in Japanese.

If current branch contains issue number, add it to commit message.
After Creating This Commit, Do not commit unless instructed.

コミット command

# Commit, Push and make Pull Request
1. If current branch is main, make new branch
2. commit with Conventional Commits

Write text in Japanese.If current branch contains issue number, add it to commit message.

## Push Branch
Push branch to remote repository.

## Make or Update Pull Request
Follow @.github/PULL_REQUEST_TEMPLATE.md for each Project.
Remove HTML comment tag before publish.
Pull Request Should be **draft** .
Write text in Japanese.

After Creating Pull Request, Do not commit unless instructed.

PR作成コマンド

最近はreviewに対する処理・返信もClaudeにやらせるためのコマンドもつくっています。

  1. PRのコードレビューをAIがおこない

  2. そのレビューコメントをClaudeが読込み必要に応じて修正

    1. 必要があれば修正し返信コメントにcommit hashを記載

    2. 必要がなければ、必要がない理由を返信コメントに記載

人間の不要感がすごく上がってきています。

#noteアドカレ2025

#note