Communitygithub.com

byteratio/iphone-dev

ネイティブiPhoneアプリ開発のための規約 — SwiftUI + SwiftData ローカルファースト、XcodeGenプロジェクト生成、CLI-onlyビルド/テスト/デプロイループ(デフォルトはシミュレータ、署名済み実機デプロイはdevicectl経由)、XCTest可視カバレッジ、無料個人チーム署名の落とし穴。iOS/iPhoneアプリ作成時、iOSターゲットやMakefileループのプロジェクト追加時、Xcode署名/プロビジョニング/デプロイ問題のデバッグ時、既存アプリのロジックをネイティブSwiftクライアントに移植する際に使用します。

iphone-dev とは?

このスキルは、SwiftUI + SwiftData をベースにしたローカルファーストのiPhoneアプリ開発のための包括的な規約を提供します。空のリポジトリから実機で動作する署名済みビルドまでのエンドツーエンドのプロセスをカバーし、特に無料の個人Appleアカウントでの開発に焦点を当てています。主な特徴は、XcodeGenを使用したプロジェクト生成(.xcodeprojをコミットしない)、シミュレータをデフォルトとするCLI-onlyのビルド/テスト/デプロイループ、XCTestによるテストとカバレッジレポート、そして無料個人チームの署名に関する具体的な落とし穴とその回避策です。また、既存のサーバーアプリのiOSクライアントを作成する場合の同期階層(シンクライアント、スナップショットミラー、スコープ付きアウトボックス)についても段階的に説明しており、小規模アプリの開発に最適化されています。

対応~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/byteratio/skills/tree/main/plugins/hechtch-skills/skills/iphone-dev

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

iPhoneアプリ開発

SwiftUIアプリを空のリポジトリから実機で動作する署名済みビルドにまで仕上げるためのエンドツーエンドの規約です。

前提: 小規模アプリ、無料の個人Appleアカウント、App Store配信なしを想定しています。有料の開発者チームの場合、以下のルールの一部が変わります — 署名セクションで該当箇所を明示します。

アーキテクチャのデフォルト

  • SwiftUI + SwiftData、ローカルファースト。 小規模アプリはサーバーに常時接続している必要はありません。データはデバイス上のSwiftDataに保存し、ネットワーク呼び出しは公開APIのみに使用します(https、ATS例外なし)。アプリが既存のバックエンドのシンクライアントとして始まった場合、"サーバーを廃止できるか?"という方向転換が発生することを想定してください — サーバーのロジックを、SwiftData配列に対する純粋なSwift関数に移植し、一台の電話のためにサーバーを生かし続ける必要をなくします。
  • SwiftDataモデリング: 整数の外部キーではなく、実際のオブジェクト間リレーションシップを使用します。自然キーには @Attribute(.unique) を使用します。SwiftDataのto-many配列は順序を保持しないため、順序が重要な場合は sortOrder フィールドと sortedX 計算プロパティを追加します。日付は文字列ではなく Date 型を使用します。Enumは String ローの Codable を使用します。
  • 動作中のインストールでのスキーマ変更: モデルやオプショナルプロパティの追加は、次回起動時に軽量マイグレーションが静かに実行されます。リネーム、削除、型変更を SchemaMigrationPlan なしで行うと、ストアを開けなくなり、デプロイ済みアプリはユーザーのデータを保持したまま起動時にクラッシュします(データは使用できません)。再デプロイ(同じバンドルID)ではデータコンテナは決して削除されません。アプリを削除する場合のみ削除されます。ユーザーが実際のデータを蓄積する前に、エクスポート/バックアップのパスを計画してください。
  • Viewは直接 @Query + modelContext にアクセスします。 本当にキャッシュが必要な場合以外は、Storeやリポジトリ層は使用しません。純粋なロジック(マッチング、パース、インポート)はenum名前空間(enum Foo { static func … })に配置し、UIなしでテスト可能にします。
  • デプロイメントターゲット: 必要なAPIが特に指定しない限り、現在のメジャーバージョンの1つ前をターゲットにします。ターゲットは1つ、TARGETED_DEVICE_FAMILY: "1"、ポートレートを基本とし、アプリが必要とする場合のみ回転を許可します。

プロジェクト生成 — XcodeGen、.xcodeprojはコミットしない

ios/project.yml を信頼できる唯一の情報源とし、.xcodeproj バンドルは生成してgitignoreします(ios/build/ および生成された Info.plist もgitignore)。ファイルの追加や削除後に再生成します — xcodegenはソースディレクトリをグロブするため、既存ファイルの編集には再生成は不要です。

  • xcodegenはGitHubリリースのzipからインストールします(PREFIX=~/.local ./install.sh) — Homebrewは不要で、制限されたMacでも動作します。
  • 単体テストターゲットには GENERATE_INFOPLIST_FILE: YES が必要です。これがないとテストバンドルが署名に失敗します。
  • project.yml でスキームを定義し、gatherCoverageData: true とテストターゲットをアタッチします。そうしないと xcodebuild test が実行するものがありません。

開発ループ — CLIのみ、デフォルトはシミュレータ

すべてのiOSプロジェクトには以下のMakefileターゲットがあります。シミュレータ名、デバイスID、チームIDは ?= 変数でパラメータ化し、マシン固有の値がハードコードされないようにします:

ターゲット内容
ios-projectxcodegen generate + Xcodeで開く
ios-simシミュレータ用に署名なしビルド、シミュレータ起動、インストール、起動 — デフォルトのループ。署名不要、パスワードプロンプトなし
ios-sim-seedios-simを実行後、--seed-demo で再起動
ios-testシミュレータで xcodebuild test + xccov によるターゲット別カバレッジレポート
ios-deploy接続された実機用の署名済みビルド + devicectl でのインストール + 起動

ios-test は実行ごとにカバレッジを表示します — ハウスルールとして、make test は常に数値を表示しますが、ハードなしきい値は設定しません。

シミュレータビルド: generic/platform=iOS コンパイルチェックでは CODE_SIGNING_ALLOWED=NO で問題ありません。シミュレータの宛先には署名はまったく不要です。シミュレータと実機では別々のデータベースがあることを忘れないでください。

常に役立つデバッグの便利機能

  • サンプルデータシーダー(DemoData.swift、#if DEBUG): 有効期限/日付フィールドが .now を基準に計算されたキュレーションされたデータセットで、べき等(再実行しても何も追加されない)。3つの方法で公開 — 設定アプリの「デベロッパ」セクションボタン、ProcessInfo.processInfo.arguments でチェックされる --seed-demo 起動引数、および ios-sim-seed ターゲット。シードがアプリの主要な状態をカバーしていることを確認するテストを追加し、静かに壊れるのを防ぎます。
  • ホイールピッカーよりも検索可能なピッカー — リストが数十エントリを超える可能性がある場合(インポートされたデータセットではほぼ確実)。
  • カメラ/スキャナー機能: DataScannerViewController.isSupported && .isAvailable をチェックし、手動入力のフォールバックを同梱します — シミュレータでも正常に動作します。

テスト

  • シミュレータでXCTestを実行。他のスタックからロジックを移植する場合は、参照テストスイートも移植し、言語間でセマンティクスを固定します。
  • 共有ヘルパー: isStoredInMemoryOnly: true でModelContainerを構築する makeInMemoryContext()。@MainActor テストクラスと setUp() async throws。
  • 結果バンドルから合格/不合格を読み取る: xcrun xcresulttool get test-results summary --path build/test.xcresult。

署名とデプロイ — 落とし穴(いずれも実際に時間を費やしました)

  • チームIDは security find-identity の括弧内の値ではありません — それは証明書自身のIDです。実際のチームIDはプロビジョニングプロファイルから取得します(security cms -D -i <profile> → application-identifier プレフィックス)またはXcodeのAccountsペインから取得します。間違ったIDを使用すると、「No Account for Team」という誤解を招くエラーが発生します。
  • -allowProvisioningUpdates はプレーンなターミナルからApple IDセッションを認識できません。 プロビジョニングプロファイルはXcode GUI(Signing & Capabilities → Team設定 → Try Again)で一度作成します。その後、純粋なCLIビルドは DEVELOPMENT_TEAM=<id> CODE_SIGN_STYLE=Automatic で動作します。
  • 初回デバイス設定の流れ: 実機でDeveloper Modeを有効にする(設定 → プライバシーとセキュリティ;このトグルはXcodeがデバイスと通信した後にのみ表示されます;再起動が必要)→ コンピュータを信頼する → 初回インストール後、開発者証明書を信頼する(設定 → 一般 → VPNとデバイス管理)。Xcodeの「your team has no devices」エラーは通常、デバイスの登録試行が、デバイスの再起動中またはロック中に行われたことを示します — 実機を実行宛先として選択し、再試行してください。
  • ビルドごとにキーチェーンプロンプトが表示される: codesignキーチェーン画面で一度常に許可をクリックすると、ビルドごとのパスワードプロンプトが表示されなくなります。
  • 無料個人チームの制限: インストールは7日で期限切れになります(再デプロイして再署名)。最大3つのサイドロードアプリ、プッシュ通知なし、App Groupsなし。有料チームはこれら4つすべてを解除します — アプリにプッシュ通知やApp Groupsが必要な場合、それが有料チームを取得するトリガーです。
  • デプロイ/起動CLI: xcrun devicectl list devices、xcrun devicectl device install app --device <id> <path>.app、… device process launch --device <id> <bundle-id>。

新品Macのセットアップ(ヘッドレスでも対応)

  1. App StoreからXcodeをインストール(macappstore://apps.apple.com/app/id497799835 を開く)。
  2. sudo xcode-select -s /Applications/Xcode.app && sudo xcodebuild -license accept && sudo xcodebuild -runFirstLaunch — 管理者権限が必要です。標準アカウントの場合は、まず管理者メンバーシップを修正します(su admin -c 'sudo dseditgroup -o edit -a <user> -t user admin')。
  3. xcodebuild -downloadPlatform iOS — iOS SDKとシミュレータランタイムは、Xcode 15以降、別の数GBのダウンロードになります。これがないと、「iOS X.Y is not installed」というエラーでビルドが失敗します。
  4. DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer をコマンドごとのオーバーライドとして使用し、xcode-selectが修正される前に使用できます。
  5. リリースzipからxcodegenを ~/.local にインストール(上記参照)。

既存サーバーアプリのコンパニオンクライアント — 同期階層

iPhoneアプリが既存のサーバー + Webアプリを持つアプリに加わる場合(サーバーが単一の情報源であり続ける)、電話のユースケースが許す最も安価な階層を選択します。まず「電話はサーバーのネットワーク外でも動作する必要があるか?」と「キャプチャか、完全な編集か?」を尋ねます:

  1. シンクライアント — ローカルストアなし。電話は既存のAPIを呼び出します。接続が確実な場合に適しています。
  2. スナップショットミラー — 完全なJSONプルからSwiftDataキャッシュを一括で再構築します(シングルユーザーDBは小さい)。マージなし → トゥームストーンなし、行ごとのタイムスタンプなし、競合エンジンなし。サーバー側の削除/編集は無料で反映されます。写真はURLキャッシュを介して遅延ロードします。
  3. スコープ付きアウトボックス — オフラインでの作成を、すでに存在するレコードの子(既知の親に対するログ、メモ、写真)に制限します。親は実際のサーバーIDを持つため、リプレイは単純なAPI呼び出しになります — 整数PKスキーマにはUUIDマイグレーションは不要です。同期イベント = アウトボックスをプッシュ、次にスナップショットをプル(自分のキャプチャは確認済みで戻ってくる)。404-孤児(「N は同期できませんでした」)を表示し、決して静かにドロップしないでください。保留中バッジ + 最終同期タイムスタンプを表示します。ユーザーが固定したサーバーアドレスが応答する場合にのみ自動同期します — 外部ネットワークをプローブしないでください。
  4. 完全双方向同期(UUID、トゥームストーン、デルタエンドポイント、LWW/CRDT) — 階層1〜3で不十分な証拠がある場合にのみ使用します。この再作業はサーバー側(クライアントが発行可能なUUID、べき等なアップサート、changes?since= + トゥームストーン)から始まり、Swiftコードを書く前に行います。

階層2と3はうまく組み合わさります。読み取り用のスナップショットミラーとキャプチャ用のスコープ付きアウトボックスで、「自宅で動作し、どこでもキャプチャ」を階層4のメカニズムなしでカバーできます。

プロジェクトの衛生状態

  • マシン固有およびデバイス固有の情報(チームID、デバイスUDID、シミュレータ名)は、Makefileの ?= 変数またはプロジェクト自身のメモに記述します — スクリプトにハードコードしたり、このスキルに記述したりしないでください。
  • 進行中の作業スライスごとに plans/<topic>.md ドキュメントを保持し、リリースした内容を追跡するためにトップレベルの CHANGELOG.md を維持します。スライスが完了したら、plans/done/<topic>.md に移動し、「Delivered in <バージョン> — <日付>」ヘッダーを追加します。
  • 各スライスのサイズは、実機またはシミュレータで実行可能なもので終わるように設定します。起動できないiOSスライスはレビューできません。

Individual skills in this repo

This repo contains 5 individual skills — each has its own dedicated page.

byteratio/example-skill

Template skill for this marketplace. Use as a starting point when adding a new skill — copy this plugin directory, rename it, and replace this description with the specific trigger conditions for your skill (what the user says or does that should invoke it).

byteratio/kanban-plans

Track multi-session plans on a locally-running kanban board (github.com/hechtch/kanban) via its agent REST API. Claim a plan, move it through todo/doing/blocked/awaiting_merge/done, leave notes, and set the git branch. Use at the start of any non-trivial multi-session plan, when resuming such a plan, or when the user asks what's on the board or where a plan stands.

byteratio/password-generator

Generates secure, memorable passwords using 3 random dictionary words with leet-speak substitutions. Use when the user asks to generate a password, create a new password, or needs a secure passphrase.

byteratio/security-sweep

Investigate whether a project (or every repo on the machine) is exposed to known and actively-exploited dependency vulnerabilities. Combines a deterministic per-ecosystem audit (npm audit, govulncheck, pip-audit, osv-scanner) with live web research into recent/active supply-chain incidents, then checks each project's lockfiles directly — the leading-indicator check that `npm audit` misses. Use when the user asks to "investigate security", "check for vulnerable dependencies", "are we affected by <a named CVE / package compromise>", "scan the projects for supply-chain issues", or wants a recurring security sweep.

byteratio/ux-agents

Scaffold persona-based UX testing agents for a web app — project-scoped .claude/agents/<persona>-ux.md files that drive a real browser via Playwright, walk user journeys as a specific persona, and report tagged friction findings. Use when setting up UX review automation, when the user asks what a specific user segment would think of the app, or after the user accepts an offer to add persona testing.

関連スキル