【Aider + Gemini】AIでiOSアプリを作ってみる!(本格的に

AI

claude codeも使いますが Aider + Geminiも試してみます。こちらは完全無料
しかし能力は 無料版の gemini 1.5 proなので落ちます。と
しかし 2.5 を使えるので同等の能力が期待できそうです。2026/8時点では
gemini-2.5-pro または gemini-3.1-pro
ただ自走でバグ修正ではないのでその点は確実に劣ります。

Aider(ターミナル上で動作するAIコーディングツール)とGemini APIを組み合わせ、XcodeでiOSアプリ開発を進める開発環境の設定手順と具体的な運用ワークフローを解説します。
AiderはGitリポジトリと連携し、直接ソースコード(.swift ファイル等)を編集・コミットしてくれるため、Xcode側でビルドや動作確認を行いながら並行して開発を進めるスタイルと非常に相性が良いです。

1. 事前準備と環境構築

① Gemini APIキーの取得

  1. Google AI Studio(aistudio.google.com)にアクセスし、APIキー(GEMINI_API_KEY)を発行します。
    https://aistudio.google.com/api-keys から 「APIキーを作成」ボタン
  2. APIキーをコピーする

② Aiderのインストール

ターミナルを開き、Aiderをインストールします。
Bash

# pipxを使用する場合(推奨)
brew install pipx
pipx install aider-chat

# またはpipを使用する場合
pip install aider-chat

失敗したので。。。uvでインストール

 % brew install uv

==> Running `brew cleanup uv`...
Disable this behaviour by setting `HOMEBREW_NO_INSTALL_CLEANUP=1`.
Hide these hints with `HOMEBREW_NO_ENV_HINTS=1` (see `man brew`).
==> Caveats
zsh completions have been installed to:
  /usr/local/share/zsh/site-functions
% uv tool install --force aider-chat
Installed 1 executable: aider
warning: `/Users/junichi/.local/bin` is not on your PATH. To use installed tools, run `export PATH="/Users/junichi/.local/bin:$PATH"` or `uv tool update-shell`.

% uv tool update-shell
Created configuration file: /Users/junichi/.zshenv
Restart your shell to apply changes
% source ~/.zshenv
% echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc
% source ~/.zshrc
% aider --version
aider 0.86.2

③ 環境変数の設定

ターミナルでAPIキーを設定します(~/.zshrc 等に追記しておく)。
echo 'export GEMINI_API_KEY="AIzaSy_your_actual_api_key_here"' >> ~/.zshrc
export GEMINI_API_KEY="your_api_key_here"

2. XcodeプロジェクトでのAider起動

AiderはGitの差分を監視して安全にコードを変更するため、プロジェクトがGit管理されている必要があります。

  1. ターミナルでXcodeプロジェクトのルートディレクトリに移動します。
  2. Gitリポジトリ化されていない場合は初期化します。
    git init
    git add .
    git commit -m "Initial commit"
  3. Geminiモデルを指定してAiderを起動します。(proが必要な時は切り替えます
    aider --model gemini/gemini-3.6-flash
% aider --model gemini/gemini-3.6-flash
────────────────────
Aider v0.86.2
Model: gemini/gemini-3.6-flash with whole edit format
Git repo: .git with 2 files
Repo-map: using 4096 tokens, auto refresh
─────────────────────
>/exit で終了

のように起動できました。

3. Xcode + Aider 実践ワークフロー

基本の役割分担は以下のようになります。

ツール役割
Xcodeコードの閲覧、キャンバス/実機でのUIプレビュー、ビルド、エラー確認
Aider(ターミナル)仕様指示、新規実装、リファクタリング、バグ修正、自動Gitコミット

ワークフローの進め方

  1. Aiderで編集したいファイルを指定します。
    /add Views/CameraViewModel.swift
  2. AIへプロンプトで実装や修正を指示します。
  3. Aiderがコードを書き換え、自動的にGitコミットを作成します。
  4. Xcodeに戻り、Cmd + B でビルドして確認します。エラーが出た場合は、ターミナルのビルドエラーログをそのままAiderに貼り付けることで、自動修復を行わせることができます。

4. Swift 6 対応の安全なコード生成プロンプト例

Aiderに対して指示を出す際は、プロジェクトの品質基準や安全性を満たすプロンプトを入力することが重要です。

指示プロンプト例

プロンプト:CameraViewModel.swift を新規作成してください。Swift 6のConcurrencyに対応した @MainActor クラスとし、カメラの設定状態(preferred)と実際の状態(active)の反映待ち確認ロジックを含むViewModelを作成してください。強制アンラップ ! は一切使用せず、guard let による安全なアンラップを徹底してください。

5. Aiderが生成するコードの成果物例

以下は、上記のような指示のもとで生成される、ビルド可能で防御的プロンプト規約を満たしたSwiftコードの例です。
Swift

import Foundation
import Combine

/// カメラ設定の状態管理を行うViewModel
/// Swift 6 Concurrencyに準拠し、UI関連処理のため@MainActorを指定
@MainActor
public final class CameraViewModel: ObservableObject {
    
    // MARK: - Published Properties
    
    /// ユーザーが望む設定値
    @Published public private(set) var preferredFrameRate: Int = 30
    
    /// 実際に反映されている設定値
    @Published public private(set) var activeFrameRate: Int = 30
    
    /// 設定反映の処理中フラグ
    @Published public private(set) var isApplyingConfiguration: Bool = false
    
    /// エラーメッセージ(画面表示用)
    @Published public me: String? = nil
    
    // MARK: - Private Properties
    
    private var cancellables = Set<AnyCancellable>()
    
    // MARK: - Initializer
    
    public init() {
        // 設定値と実際の状態の乖離を監視するサンプルロジック
        setupObservation()
    }
    
    deinit {
        // MainActorクラスのdeinitでの処理
        cancellables.removeAll()
    }
    
    // MARK: - Public Methods
    
    /// フレームレート変更リクエスト(設定値と実際の状態の反映待ちを含む)
    /// - Parameter targetFPS: 設定したいフレームレート
    public func updateFrameRate(to targetFPS: Int) async {
        guard targetFPS > 0 else {
            self.errorMessage = "無効なフレームレートが指定されました: \(targetFPS)"
            return
        }
        
        self.preferredFrameRate = targetFPS
        self.isApplyingConfiguration = true
        self.errorMessage = nil
        
        do {
            // 実際のデバイス設定変更(非同期処理のシミュレーション)
            try await applyDeviceConfiguration(fps: targetFPS)
            
            // 設定反映待ちの確認ロジック(乖離のチェック)
            let isVerified = await verifyConfigurationApplied(expectedFPS: targetFPS)
            
            if isVerified {
                self.activeFrameRate = targetFPS
            } else {
                self.errorMessage = "設定の反映確認に失敗しました。設定値と実際の状態に乖離があります。"
                // フォールバック: 実際の状態に preferred を戻す
                self.preferredFrameRate = self.activeFrameRate
            }
        } catch {
            // エラーハンドリングとフォールバック処理
            self.errorMessage = "フレームレートの設定変更中にエラーが発生しました: \(error.localizedDescription)"
            self.preferredFrameRate = self.activeFrameRate
        }
        
        self.isApplyingConfiguration = false
    }
    
    // MARK: - Private Helper Methods
    
    private func setupObservation() {
        // [weak self] を使用した安全なクロージャ処理
        $preferredFrameRate
            .combineLatest($activeFrameRate)
            .sink { [weak self] preferred, active in
                guard let self = self else { return }
                if preferred != active && !self.isApplyingConfiguration {
                    print("[Log] 警告: 設定値(\(preferred))と実際の状態(\(active))の間に乖離が存在します。")
                }
            }
            .store(in: &cancellables)
    }
    
    private func applyDeviceConfiguration(fps: Int) async throws {
        // デバイスへの反映処理(擬似非同期処理)
        try await Task.sleep(nanoseconds: 500_000_000) // 0.5秒の反映待ち
    }
    
    private func verifyConfigurationApplied(expectedFPS: Int) async -> Bool {
        // 実際のハードウェア状態を読み取って確認するロジック(擬似処理)
        try? await Task.sleep(nanoseconds: 200_000_000)
        return true
    }
}

6. Aider利用時のポイント

  • .aider.conf.yml の活用: プロジェクトルートに .aider.conf.yml ファイルを置き、コーディング規約(例:「!禁止」「guard let徹底」「@MainActor使用」など)をあらかじめ記載しておくと、毎回指示文へ書かずに自動で適用されます。
  • コンパイルエラーの共有: Xcodeのビルドで発生したエラー(Cmd + Shift + M でエラーテキストをコピー可能)をそのまま Aider に貼り付けると、問題の箇所を正確に修正してくれます。
  • Gitの履歴チェック: Aiderは変更のたびに自動で小刻みにコミットを作成するため、不意な書き換えがあった場合でも git reset や Xcode の Git インテグレーションから簡単にロールバック可能です。

7.コミット時のコメントを残す

.aider.conf.yml に設定を残す

# 使用するモデルの指定
model: gemini/gemini-3.6-flash

# 自動コミットの有効化
auto-commits: true

# コミットメッセージのカスタマイズ(シンプル版)
commit-prompt: "変更内容を要約し、日本語で『feat: 〇〇』や『fix: 〇〇』の形式でコミットメッセージを作成してください。"

8. aider開発ブランチから本番リポジトリへの反映

main > develop > dev-aider-123 のようにブランチを作ってdev-aiderで開発を進める

完成後のmergeはdevelopに

# 1. develop に戻る
git checkout develop

# 2. Aiderブランチの変更を1つにまとめてマージ
git merge --squash feature/dev-aider-swiftdata

# 3. developにコミット
git commit -m "feat: SwiftDataによるユーザー設定保持機能を追加"

# 4. (任意) 使い終わった作業ブランチを削除
git branch -D feature/dev-aider-swiftdata

squashをつけることですべてを保存せず、task単位でまとめて1コミットに整理する
(全ログ残したい場合は普通にmergeでも。

AI Studioのレート制限、使用量チェック

RPM 1分あたり TPM 1分あたり RPD 一日あたり。らしいです。

Gemini 3.6 flashを使い切ったところ

RPDは 夏時間16時、冬時間17時にリセットされるようです!

Webの生成AIと何が違う?

geminiの能力は同じです、aiderを挟むことでファイルチェック、編集を自動化できます

指示を出すと大体のことはできるので、

制限はwebとは別なのでwebで相談、設計してからaiderを通して作業してもらう感じでだいぶ楽ですね

動けば良い、結果重視のツール作成はAIを使うべきですね

お気軽にコメントください!

スパム対応のためコメント認証に数日かかることがありますが、お気軽にコメントいただけると嬉しいです^^

コメント

タイトルとURLをコピーしました