Tworzenie aplikacji iOS z agentami AI: Przewodnik praktyka
# Tworzenie aplikacji iOS z agentami AI
TL;DR: Trzy środowiska agentowe umożliwiają obecnie tworzenie kodu dla iOS: Claude Code CLI z MCP, Codex CLI z MCP oraz natywni agenci Intelligence w Xcode 26.3. Dwa serwery MCP (XcodeBuildMCP z 59 narzędziami i
xcrun mcpbridgeod Apple z 20 narzędziami) zapewniają agentom ustrukturyzowany dostęp do kompilacji, testów, symulatorów i debugowania. Niniejszy przewodnik obejmuje rzeczywiste wzorce CLAUDE.md, konfiguracje hooków oraz rzetelne oceny tego, co działa, a co zawodzi — na podstawie 8 produkcyjnych aplikacji iOS obejmujących łącznie 293 pliki Swift. Agenci radzą sobie doskonale z widokami SwiftUI, modelami SwiftData, refaktoryzacją i diagnozowaniem błędów kompilacji. Zawodzą przy modyfikacjach .pbxproj, podpisywaniu kodu i debugowaniu wizualnym. Przepaść między „agent pisze w Swift” a „agent publikuje aplikację iOS” można pokonać przez konfigurację, nie przez promptowanie.
Tworzę 8 aplikacji iOS z pomocą agentów AI. To nie prototypy — to aplikacje w App Store, z integracjami HealthKit, shaderami Metal, fizyką SpriteKit, synchronizacją iCloud, Live Activities, tablicami wyników Game Center i celami wieloplatformowymi obejmującymi iOS, watchOS i tvOS. Każda linia Swift w tych aplikacjach została albo napisana przez agenta i zrecenzowana przeze mnie, albo napisana przeze mnie i zrefaktoryzowana przez agenta. Według moich szacunków proporcja wynosi mniej więcej 85/15 na korzyść agenta.
Ten przewodnik to kompendium, którego brakowało mi na początku. Obejmuje cały stos: które środowisko agentowe wybrać, jak skonfigurować serwery MCP zapewniające ustrukturyzowany dostęp do kompilacji, co umieścić w pliku CLAUDE.md, które hooki uchronią agenta przed zniszczeniem projektu Xcode — i, co kluczowe — gdzie agenci zawodzą i trzeba przejąć stery.
Kluczowe wnioski
Dla programistów iOS nowych w świecie agentów AI:
- Zacznij od Claude Code CLI + XcodeBuildMCP. To najdojrzalsze środowisko z najszerszym pokryciem narzędzi MCP. Wystarczy zainstalować dwa polecenia, dodać CLAUDE.md do projektu, a agent będzie mógł kompilować, testować i debugować bez konieczności ręcznego kopiowania komunikatów o błędach.
- Nigdy nie pozwól agentowi modyfikować .pbxproj. To najważniejsza reguła. Hook PreToolUse blokujący zapis do
.pbxproji.xcodeproj/zaoszczędzi wielu godzin odzyskiwania projektu. - CLAUDE.md to dokument wdrożeniowy agenta. Każda godzina poświęcona na CLAUDE.md oszczędza dziesięć godzin poprawiania błędów agenta.
Dla doświadczonych użytkowników agentów dodających iOS do swojego przepływu pracy:
- MCP zmienia pętlę kompilacji iOS. Przed MCP agenci pisali w Swift, ale nie mogli zweryfikować, czy kod się kompiluje. Dzięki XcodeBuildMCP agent pisze kod, kompiluje go, odczytuje ustrukturyzowane błędy, naprawia je i uruchamia testy — autonomicznie.
- Trzy środowiska służą różnym celom. Claude Code CLI do głębokich sesji agentowych, Codex CLI do headless przetwarzania wsadowego, natywni agenci Xcode 26.3 do szybkich poprawek inline bez opuszczania IDE.
- Infrastruktura hooków przenosi się bezpośrednio. Istniejące formattery PostToolUse, blokery PreToolUse i hooki uruchamiające testy działają identycznie w projektach iOS — wymagają jedynie drobnych zmian ścieżek.
Dla liderów zespołów oceniających wspomagane przez AI tworzenie aplikacji iOS:
- Skuteczność agenta skaluje się z dokumentacją projektu, nie z jego rozmiarem. Aplikacja o 63 plikach ze szczegółowym CLAUDE.md generuje lepsze wyniki agenta niż aplikacja o 14 plikach bez dokumentacji.
- Granica .pbxproj jest bezwzględna. Agenci nie potrafią niezawodnie edytować plików projektu Xcode. Przepływ pracy musi uwzględniać ręczne dodawanie plików do celów Xcode.
- Uczciwa ROI: agenci obsługują 70–80% prac implementacyjnych. Pozostałe 20–30% — dopracowanie wizualne, podpisywanie, optymalizacja wydajności, publikacja w App Store — wymaga ludzkiej oceny.
Wybierz swoją ścieżkę
| Czego potrzebujesz | Przejdź tutaj |
|---|---|
| Pierwsza konfiguracja MCP | Konfiguracja MCP: Kompletny przewodnik — instalacja obu serwerów, weryfikacja, konfiguracja agentów |
| Napisanie CLAUDE.md dla projektu iOS | Wzorce CLAUDE.md dla projektów iOS — rzeczywiste przykłady z 8 aplikacji |
| Porównanie trzech środowisk agentowych | Trzy środowiska agentowe dla iOS — Claude Code vs. Codex vs. natywny Xcode |
| Zrozumienie możliwości i ograniczeń agentów | W czym agenci są dobrzy i W czym agenci zawodzą |
| Konfiguracja hooków dla rozwoju iOS | Hooki dla rozwoju iOS — formatowanie przy zapisie, ochrona .pbxproj, uruchamianie testów |
| Pełna dokumentacja referencyjna (ta strona) | Czytaj dalej — wszystko od konfiguracji po zaawansowane wzorce |
Jak korzystać z tego przewodnika
To ponad 3000 linii dokumentacji referencyjnej. Zacznij od miejsca odpowiadającego Twojemu poziomowi doświadczenia:
| Doświadczenie | Zacznij tutaj | Następnie poznaj |
|---|---|---|
| Nowy w iOS + agentach | Wymagania wstępne → Konfiguracja MCP → Pierwsza sesja z agentem | Wzorce CLAUDE.md, Co działa / nie działa |
| Programista iOS, nowy w agentach | Trzy środowiska → Konfiguracja MCP → CLAUDE.md | Hooki, Wzorce architektoniczne |
| Użytkownik agentów, nowy w iOS | Wzorce architektoniczne → W czym agenci zawodzą → CLAUDE.md | Kontekst specyficzny dla frameworków, Zaawansowane przepływy pracy |
| Doświadczony w obu dziedzinach | Zaawansowane przepływy pracy → Hooki → Wzorce wieloplatformowe | Macierz porównawcza środowisk, Portfolio |
Spis treści
- Portfolio: 8 aplikacji, 293 pliki
- Wymagania wstępne
- Trzy środowiska agentowe dla iOS
- Konfiguracja MCP: Kompletny przewodnik
- Wzorce CLAUDE.md dla projektów iOS
- Pierwsza sesja z agentem
- W czym agenci są dobrzy w iOS
- W czym agenci zawodzą w iOS
- Hooki dla rozwoju iOS
- Wzorce architektoniczne współpracujące z agentami
- Kontekst specyficzny dla frameworków
- Wzorce wieloplatformowe
- Zaawansowane przepływy pracy
- Studia przypadków z praktyki
- Cykl życia projektu z agentami
- Konfigurowanie definicji agentów
- Wzorce testowania dla iOS wspomaganego przez agentów
- Zarządzanie oknem kontekstu w projektach iOS
- Rozwiązywanie problemów
- Typowe błędy agentów w iOS i jak im zapobiegać
- Uczciwa ocena
- FAQ
- Karta szybkiego odniesienia
- Bibliografia
Powiązane zasoby
| Temat | Zasób |
|---|---|
| Konfiguracja MCP dla Xcode (krótszy wpis na blogu) | Dwa serwery MCP uczyniły Claude Code systemem kompilacji iOS |
| Kompletna dokumentacja Claude Code CLI | Claude Code CLI: Kompletny przewodnik |
| Dokumentacja Codex CLI | Codex CLI: Kompletny przewodnik |
| Szczegółowy opis systemu hooków | Anatomia pazura: 84 hooki jako warstwa orkiestracji |
| Wzorce architektury agentowej | Przewodnik po architekturze agentowej |
Portfolio: 8 aplikacji, 293 pliki
Zanim przejdziemy do konfiguracji, warto przedstawić źródło, z którego czerpie ten przewodnik. To nie są projekty demonstracyjne — obejmują pięć frameworków Apple, trzy platformy i pełne spektrum złożoności iOS, od 14-plikowego trackera treningów po 63-plikowy wieloplatformowy timer medytacyjny.
| Aplikacja | Stos technologiczny | Pliki | Złożoność |
|---|---|---|---|
| Banana List | SwiftUI + SwiftData + synchronizacja iCloud Drive + serwer MCP dla Claude Desktop | 53 | Pełny CRUD, synchronizacja iCloud, niestandardowy serwer MCP udostępniający dane aplikacji do Claude Desktop |
| Ace Citizenship | Aplikacja do nauki SwiftUI + backend FastAPI | 26 | Klient-serwer, integracja REST API, silnik quizów |
| TappyColor | Gra dopasowywania kolorów w SpriteKit | 30 | Pętla gry, fizyka, obsługa dotyku, efekty cząsteczkowe |
| Return | Timer medytacji zen — iOS 26+, watchOS, tvOS | 63 | HealthKit, Live Activities, rozszerzony czas wykonania Watch, nawigacja fokusowa na TV, synchronizacja sesji przez iCloud |
| amp97 | Shadery Metal + wizualizacja dźwięku | 41 | Niestandardowy potok renderowania Metal, analiza audio, obliczenia GPU w czasie rzeczywistym |
| Reps | SwiftUI + SwiftData — śledzenie treningów | 14 | Minimalna aplikacja, czyste wzorce SwiftData |
| Water | SwiftUI + SwiftData + Metal + HealthKit — śledzenie nawodnienia | 34 | Symulacja płynów w Metal, logowanie spożycia wody przez HealthKit, widget |
| Starfield Destroyer | SpriteKit + Metal — kosmiczna strzelanka | 32 | 99 poziomów, 8 statków, tablice wyników Game Center, post-processing Metal |
Dlaczego liczba plików ma znaczenie: Skuteczność agenta koreluje z czytelnością projektu, nie z jego rozmiarem. Return (63 pliki) generuje lepsze wyniki agenta niż amp97 (41 plików), ponieważ Return posiada szczegółowy CLAUDE.md z adnotacjami plików, diagramami architektury i jawnie opisanymi wzorcami. Shadery Metal w amp97 są z natury trudniejsze do analizy przez agentów, niezależnie od jakości dokumentacji.
Wymagania wstępne
Przed skonfigurowaniem dowolnego środowiska uruchomieniowego agenta do programowania iOS:
Wymagane: - macOS 15+ (Sequoia) lub macOS Tahoe - Xcode 26.3+ zainstalowany i skonfigurowany (zaakceptowana umowa licencyjna, pobrane platformy) - Co najmniej jedno środowisko uruchomieniowe iOS Simulator - Konto Anthropic API (dla Claude Code) lub konto OpenAI (dla Codex)
Zalecane:
- SwiftFormat zainstalowany (brew install swiftformat) — używany przez hooki automatycznego formatowania przy zapisie
- SwiftLint zainstalowany (brew install swiftlint) — opcjonalny, ale przydatny do egzekwowania stylu kodu
- Znajomość terminala — wszystkie trzy środowiska uruchomieniowe działają z poziomu wiersza poleceń lub integrują się z nim
Weryfikacja instalacji Xcode:
# Check Xcode version
xcodebuild -version
# Expected: Xcode 26.3 or later
# Check available simulators
xcrun simctl list devices available
# Expected: at least one iPhone simulator
# Verify xcrun mcpbridge is available
xcrun mcpbridge --help
# Expected: usage information (not "command not found")
Jeśli xcrun mcpbridge zwraca „command not found”, potrzebny jest Xcode 26.3 lub nowszy. Można go zainstalować lub zaktualizować przez App Store albo na stronie developer.apple.com. Uwaga: xcode-select --install instaluje jedynie Command Line Tools, które nie zawierają mcpbridge — wymagana jest pełna aplikacja Xcode.app.
Trzy środowiska uruchomieniowe agentów dla iOS
Trzy odrębne środowiska uruchomieniowe potrafią pisać, budować i testować kod iOS. Nie są one wymienne — każde ma inne mocne strony, inne wzorce integracji z MCP i inne optymalne przypadki użycia.
1. Claude Code CLI
Czym jest: Terminalowy asystent kodowania od Anthropic działający w trybie agentowym. Odczytuje bazę kodu, wykonuje polecenia, modyfikuje pliki i łączy się z zewnętrznymi narzędziami przez MCP.
Integracja z MCP: Pełne wsparcie zarówno dla XcodeBuildMCP, jak i Apple Xcode MCP. Agent odkrywa narzędzia przez protokół MCP i wywołuje je ze strukturalnymi parametrami. 59 + 20 narzędzi łącznie z obu serwerów.
Konfiguracja:
# Install Claude Code (if not already installed)
claude --version # verify installation
# Add XcodeBuildMCP (59 tools — builds, tests, simulators, debugging)
claude mcp add XcodeBuildMCP \
-s user \
-e XCODEBUILDMCP_SENTRY_DISABLED=true \
-- npx -y xcodebuildmcp@latest mcp
# Add Apple Xcode MCP (20 tools — file ops, diagnostics, Swift REPL, previews)
claude mcp add --transport stdio xcode \
-s user -- xcrun mcpbridge
Najlepszy do: Głębokich sesji implementacyjnych — budowania nowych funkcji, refaktoryzacji w wielu plikach, debugowania złożonych problemów, autonomicznego wykonywania pętli buduj-testuj-naprawiaj. Okno kontekstu Claude Code o pojemności 1M tokenów (z Opus 4.6) pozwala agentowi utrzymać w pamięci roboczej większość małych i średnich projektów iOS — z doświadczenia, do około 50 plików w zależności od ich rozmiaru.
Typowa sesja:
You: Add a new SettingsView with toggles for notifications and haptic feedback.
Use the existing Settings.swift pattern from TimerManager.
Build for simulator after implementation and fix any errors.
Claude: [reads Settings.swift, TimerManager.swift, existing views]
[creates SettingsView.swift]
[calls build_sim via MCP]
[reads structured error: missing import HealthKit]
[fixes import]
[calls build_sim again — success, 0 errors, 1 warning]
[calls test_sim — all tests pass]
Kluczowa różnica w porównaniu z przepływem pracy sprzed MCP: agent nigdy nie prosi o ręczne budowanie ani wklejanie komunikatów o błędach. Pętla buduj-błąd-napraw działa autonomicznie.
2. Codex CLI
Czym jest: Terminalowy agent kodowania od OpenAI. Koncepcyjnie podobny do Claude Code, ale wykorzystuje modele OpenAI (GPT-4o, o3) i ma inny model uprawnień.
Integracja z MCP: Codex obsługuje MCP poprzez polecenie codex mcp add. Apple Xcode MCP działa bezpośrednio:
# Add Apple Xcode MCP to Codex
codex mcp add xcode -- xcrun mcpbridge
XcodeBuildMCP również działa z Codex za pomocą tego samego polecenia npx:
# Add XcodeBuildMCP to Codex
codex mcp add XcodeBuildMCP -- npx -y xcodebuildmcp@latest mcp
Najlepszy do: Bezobsługowych operacji wsadowych, integracji z CI/CD oraz zadań, w których pożądana jest druga opinia od innej rodziny modeli. Tryb sandbox w Codex uruchamia kod w izolowanych środowiskach, co jest przydatne przy destrukcyjnych operacjach, takich jak uruchamianie zestawów testów modyfikujących stan.
Kluczowe różnice w stosunku do Claude Code:
- Wykorzystuje modele OpenAI zamiast modeli Claude
- Inne rozmiary okna kontekstu i ekonomia tokenów
- Model uprawnień oparty na sandboxie (domyślnie bardziej restrykcyjny)
- Mniejszy ekosystem MCP (mniej przetestowanych serwerów społecznościowych)
- System hooków dostępny (v0.119.0+), ale mniej dojrzały niż w Claude Code — mniej typów zdarzeń i brak warunkowego pola if
Kiedy wybrać Codex zamiast Claude Code do iOS:
Codex warto użyć, gdy zależy nam na różnorodności modeli — drugi agent przeglądający kod napisany przez pierwszego wychwytuje inne klasy błędów. Przepływ pracy collab (Claude buduje, Codex recenzuje) jest skuteczny w iOS, ponieważ wzorce SwiftUI, które wyglądają poprawnie dla jednej rodziny modeli, mogą zawierać subtelne problemy wychwytywane przez drugą. Shadery Metal i wzorce współbieżności szczególnie zyskują na recenzji przez dwa modele.
3. Natywni agenci Xcode 26.3
Czym jest: Apple zintegrowało agentów kodowania opartych na AI bezpośrednio w panelu Intelligence w Xcode. Od wersji Xcode 26.3 można skonfigurować Claude Agent i Codex jako dostawców Intelligence w Xcode Settings > Intelligence.
Konfiguracja:
- Otworzyć Xcode 26.3+
- Przejść do Settings > Intelligence
- Dodać nowego dostawcę:
- Dla Claude: wybrać „Claude Agent”, wprowadzić klucz Anthropic API
- Dla Codex: wybrać „Codex”, wprowadzić klucz OpenAI API
- Agent pojawia się w pasku bocznym Intelligence i można go wywołać bezpośrednio w edytorze
Najlepszy do: Szybkich edycji inline, uzupełniania kodu z rozumowaniem na poziomie agenta oraz dla programistów, którzy wolą nie opuszczać Xcode. Natywna integracja oznacza, że agent ma bezpośredni dostęp do kontekstu projektu Xcode — otwartych plików, celów budowania, konfiguracji schematów — bez konieczności mostkowania przez MCP.
Ograniczenia w porównaniu z agentami CLI: - Brak systemu hooków — nie można wymusić formatowania przy zapisie ani blokować zapisów .pbxproj - Brak ładowania CLAUDE.md — agent nie odczytuje plików konfiguracyjnych na poziomie projektu - Ograniczona autonomia — agent operuje na bieżącym pliku lub zaznaczeniu, nie na całym projekcie - Brak delegacji do podagentów — złożone wieloetapowe zadania nie mogą być zrównoleglone - Brak konfiguracji serwerów MCP — agent korzysta wyłącznie z wbudowanych narzędzi Xcode
Kiedy używać natywnych agentów Xcode:
Do szybkich, punktowych edycji, gdy przełączanie się do terminala stanowi zbędny narzut. „Dodaj właściwość obliczaną do tego modelu.” „Napisz test jednostkowy dla tej funkcji.” „Zrefaktoryzuj ten widok, aby używał @Observable.” Zadania obejmujące jeden lub dwa pliki, niewymagające cyklu budowania i testowania.
Do wszystkiego, co wymaga budowania, testowania, refaktoryzacji wielu plików lub autonomicznej korekcji błędów, należy użyć agenta CLI z MCP.
Macierz porównawcza środowisk uruchomieniowych
| Możliwość | Claude Code CLI | Codex CLI | Xcode 26.3 natywny |
|---|---|---|---|
| Obsługa MCP | Pełna (79 narzędzi) | Pełna (79 narzędzi) | Tylko wbudowane narzędzia Xcode |
| System hooków | Tak (dojrzały) | Tak (podstawowy, v0.119.0+) | Nie |
| CLAUDE.md / konfiguracja projektu | Tak | Odpowiednik codex.md | Nie |
| Autonomiczna pętla buduj-testuj-napraw | Tak (przez MCP) | Tak (przez MCP) | Częściowa (tylko inline) |
| Delegacja do podagentów | Tak (do 10 równolegle) | Nie | Nie |
| Okno kontekstu | 1M tokenów (Opus 4.6) | Zależy od modelu | Zależy od dostawcy |
| Operacje wieloplikowe | Pełny dostęp do bazy kodu | Pełny dostęp do bazy kodu | Bieżący plik / zaznaczenie |
| Ochrona .pbxproj | Przez hooki | Ręczna | Nie dotyczy (natywna obsługa Xcode) |
| Formatowanie przy zapisie | Przez hooki PostToolUse | Zewnętrzne narzędzia | Ustawienia Xcode |
| Praca offline | Nie | Nie | Nie |
| Model kosztów | Użycie Anthropic API | Użycie OpenAI API | Użycie API dostawcy |
Rekomendacja: Claude Code CLI jako podstawowe środowisko uruchomieniowe. Natywni agenci Xcode 26.3 do szybkich edycji inline. Codex CLI do przeglądów kodu i operacji wsadowych. Te trzy środowiska wzajemnie się uzupełniają, a nie konkurują.
Konfiguracja MCP: Kompletny przewodnik
MCP (Model Context Protocol) to element, który przekształca agenta z „pisze kod Swift i ma nadzieję, że go zbudujesz” w „pisze kod Swift, buduje go, odczytuje ustrukturyzowane błędy i naprawia je”. Ta sekcja wykracza poza wpis na blogu — obejmuje oba serwery, wszystkie metody instalacji, weryfikację oraz konfigurację agenta zapewniającą faktyczne wykorzystanie narzędzi.
XcodeBuildMCP: 59 narzędzi do bezobsługowego programowania iOS
XcodeBuildMCP opakowuje xcodebuild, xcrun simctl oraz LLDB w 59 ustrukturyzowanych narzędzi MCP. Działa bez uruchomionego Xcode — cały cykl budowania, testowania i debugowania odbywa się bezobsługowo za pomocą narzędzi wiersza poleceń Apple.
Opcje instalacji:
# Option 1: Via npx (recommended — always uses latest version)
claude mcp add XcodeBuildMCP \
-s user \
-e XCODEBUILDMCP_SENTRY_DISABLED=true \
-- npx -y xcodebuildmcp@latest mcp
# Option 2: Via Homebrew (pinned version, manual updates)
brew install xcodebuildmcp
claude mcp add XcodeBuildMCP \
-s user \
-e XCODEBUILDMCP_SENTRY_DISABLED=true \
-- xcodebuildmcp mcp
# Option 3: Project-scoped (omit -s user)
claude mcp add XcodeBuildMCP \
-e XCODEBUILDMCP_SENTRY_DISABLED=true \
-- npx -y xcodebuildmcp@latest mcp
Flaga -s user udostępnia serwer globalnie we wszystkich projektach. Pominięcie jej powoduje instalację w zakresie projektu (przydatne, gdy MCP ma być dostępne tylko w projektach iOS, a nie webowych).
Zmienna środowiskowa -e XCODEBUILDMCP_SENTRY_DISABLED=true wyłącza telemetrię raportów awarii. XcodeBuildMCP domyślnie zawiera Sentry, który wysyła dane o błędach, w tym ścieżki plików. Warto zrezygnować, chyba że chcesz przekazywać dane diagnostyczne do projektu.1
Pełny zestaw narzędzi (59 narzędzi w 8 kategoriach):
| Kategoria | Narzędzia | Zastosowanie |
|---|---|---|
| Wykrywanie projektów | discover_projs, list_schemes, list_targets |
Znajdowanie plików .xcodeproj/.xcworkspace, wyświetlanie dostępnych schematów i celów |
| Budowanie | build_sim, build_device, build_mac |
Budowanie z ustrukturyzowanym wyjściem błędów/ostrzeżeń JSON według pliku i linii |
| Testowanie | test_sim, test_device |
Uruchamianie testów z wynikami dla każdej metody |
| Cykl życia symulatora | list_sims, boot_sim, shutdown_sim, open_sim, session_set_defaults |
Tworzenie, uruchamianie, zarządzanie i konfiguracja symulatorów |
| Zarządzanie urządzeniami | list_devices, install_device, launch_device |
Wdrażanie i zarządzanie urządzeniami fizycznymi |
| Debugowanie | debug_attach_sim, debug_attach_device, debug_breakpoint, debug_stack, debug_variables, debug_eval, debug_continue, debug_step, debug_detach |
Pełna integracja LLDB z punktami przerwania i inspekcją zmiennych |
| Automatyzacja UI | snapshot_ui, screenshot, tap, swipe, type_text |
Zautomatyzowana interakcja i przechwytywanie wizualne |
| Tworzenie szkieletu projektu | create_project, add_file, add_package |
Tworzenie projektów i dodawanie zależności |
Najważniejsze narzędzia do codziennej pracy:
-
build_sim— To narzędzie będzie wywoływane setki razy. Zwraca JSON z błędami skategoryzowanymi według pliku, linii i ważności. Agent odczytuje błąd, przechodzi do pliku i naprawia go bez konieczności interwencji. -
test_sim— Zwraca wyniki dla każdej metody testowej. Agent wie dokładnie, który test nie przeszedł i dlaczego, a nie tylko „testy nie przeszły”. -
list_sims+boot_sim— Zarządzanie symulatorem bez zapamiętywania flagxcrun simctl. Agent wykrywa dostępne środowiska uruchomieniowe i wybiera odpowiednie urządzenie. -
discover_projs+list_schemes— Introspekcja projektu. Agent nie musi zgadywać nazwy schematu ani struktury workspace. -
debug_attach_sim+debug_stack+debug_variables— Zdalne debugowanie LLDB. Agent może ustawiać punkty przerwania, inspekcjonować zmienne i krokowo przechodzić przez kod bez konieczności otwierania debuggera.
Apple Xcode MCP: 20 narzędzi łączących się z Xcode
Serwer MCP Apple jest dostarczany z Xcode 26.3 za pośrednictwem xcrun mcpbridge. Komunikuje się z uruchomionym procesem Xcode przez XPC (framework komunikacji międzyprocesowej Apple), udostępniając stan wewnętrzny niedostępny dla żadnego narzędzia CLI.
Instalacja:
# Standard installation (global)
claude mcp add --transport stdio xcode \
-s user -- xcrun mcpbridge
# For Codex CLI
codex mcp add xcode -- xcrun mcpbridge
Wymaga Xcode 26.3+ i uruchomionego procesu Xcode. Jeśli Xcode nie jest otwarty, każde wywołanie MCP przez ten serwer zakończy się niepowodzeniem lub zawieszeniem. XcodeBuildMCP nie ma tego ograniczenia.
Zestaw narzędzi (20 narzędzi w 5 kategoriach):
| Kategoria | Narzędzia | Zastosowanie |
|---|---|---|
| Operacje na plikach | XcodeRead, XcodeWrite, XcodeUpdate, XcodeGlob, XcodeGrep |
Odczyt/zapis plików w kontekście projektu Xcode |
| Budowanie i testowanie | BuildProject, GetBuildLog, RunAllTests, RunSomeTests |
Budowanie i testowanie z wewnętrznym systemem budowania Xcode |
| Diagnostyka | XcodeListNavigatorIssues, XcodeRefreshCodeIssuesInFile |
Diagnostyka kodu w czasie rzeczywistym (nie tylko błędy budowania) |
| Kod i dokumentacja | ExecuteSnippet, DocumentationSearch |
Wykonywanie Swift REPL i wyszukiwanie w dokumentacji Apple |
| Podglądy | RenderPreview |
Bezobsługowe renderowanie podglądów SwiftUI |
Narzędzia unikalne dla Apple MCP (niedostępne w XcodeBuildMCP):
-
DocumentationSearch— Przeszukuje dokumentację deweloperską Apple, w tym sesje WWDC. Szybsze i bardziej niezawodne niż wyszukiwanie w sieci dla pytań dotyczących API Apple. Wystarczy zapytać „czy HKQuantityType(.dietaryWater) jest prawidłowe?” i uzyskać definitywną odpowiedź ze źródła. -
ExecuteSnippet— Wykonywanie Swift REPL w kontekście projektu. Agent może weryfikować zachowanie API, testować konwersje typów i walidować wyrażenia bez budowania całej aplikacji. -
RenderPreview— Renderuje podglądy SwiftUI bezobsługowo. Agent może sprawdzić, czy widok renderuje się bez błędów, choć nie jest w stanie ocenić poprawności wizualnej (render jest zwracany jako dane, a nie inspekcjonowany wizualnie). -
XcodeListNavigatorIssues— Zwraca diagnostykę w czasie rzeczywistym z analizatora Xcode, nie tylko błędy budowania. Wykrywa problemy takie jak nieużywane zmienne, potencjalne cykle retain i ostrzeżenia o deprecjacji, których system budowania nie ujawnia.
Dlaczego oba serwery
Pokrywają się w zakresie budowania i testowania, ale różnią się fundamentalnie:
┌─────────────────────────────────────────────────────────────────┐
│ MCP TOOL COVERAGE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ XcodeBuildMCP (59 tools) Apple Xcode MCP (20 tools) │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ Standalone │ │ Requires Xcode │ │
│ │ (no Xcode process) │ │ (XPC bridge) │ │
│ │ │ │ │ │
│ │ ✓ Simulators │ BOTH │ ✓ Documentation │ │
│ │ ✓ Real devices │ ┌─────┐ │ ✓ Swift REPL │ │
│ │ ✓ LLDB debugging │ │Build│ │ ✓ SwiftUI previews │ │
│ │ ✓ UI automation │ │Test │ │ ✓ Live diagnostics │ │
│ │ ✓ Project scaffold │ └─────┘ │ ✓ Analyzer issues │ │
│ │ ✓ Screenshot │ │ │ │
│ └─────────────────────┘ └─────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
XcodeBuildMCP stosuje się do: Cyklu budowania, testowania i debugowania. Działa bez otwartego Xcode, zużywa mniej pamięci systemowej i zapewnia bogatsze zarządzanie symulatorami i urządzeniami. To główne narzędzie do budowania.
Apple Xcode MCP stosuje się do: Wyszukiwania w dokumentacji, weryfikacji Swift REPL, renderowania podglądów SwiftUI i diagnostyki w czasie rzeczywistym. Warto mieć otwarty Xcode podczas sesji wymagających tych możliwości.
W praktyce: XcodeBuildMCP obsługuje ~90% wywołań MCP, a Apple Xcode MCP służy do dokumentacji i weryfikacji REPL. Agent domyślnie używa XcodeBuildMCP do budowania i testowania, ponieważ jest szybszy (brak narzutu procesu Xcode) i bardziej niezawodny (brak zależności od XPC).
Weryfikacja
Po zainstalowaniu obu serwerów należy zweryfikować ich połączenie:
# List all configured MCP servers
claude mcp list
# Expected output includes:
# XcodeBuildMCP: npx -y xcodebuildmcp@latest mcp - Connected
# xcode: xcrun mcpbridge - Connected
Jeśli serwer wyświetla status „Disconnected” lub nie pojawia się:
- XcodeBuildMCP nie łączy się: Należy upewnić się, że Node.js jest zainstalowany (
node --version). Polecenienpxwymaga Node.js 18+. - Apple Xcode MCP nie łączy się: Należy upewnić się, że Xcode 26.3+ jest zainstalowany, a polecenie
xcrun mcpbridgedziała w terminalu. Xcode należy otworzyć przynajmniej raz, aby zaakceptować umowę licencyjną. - Oba nie pojawiają się: Należy ponownie uruchomić Claude Code (
claudew nowym terminalu). Serwery MCP zarejestrowane w trakcie sesji mogą nie pojawiać się do momentu restartu.
Uczenie agenta korzystania z MCP
Instalacja serwerów MCP jest konieczna, ale niewystarczająca. Bez wyraźnych wskazówek agent może wrócić do uruchamiania xcodebuild przez Bash (nieustrukturyzowane wyjście, zmarnowane tokeny kontekstu) lub korzystania z wyszukiwania w sieci dla dokumentacji Apple (wolniejsze, mniej niezawodne).
Należy dodać poniższy fragment do CLAUDE.md lub definicji agenta:
## Budowanie i testowanie — zawsze używaj MCP
Preferuj narzędzia MCP zamiast surowych poleceń powłoki dla WSZYSTKICH operacji budowania:
- **Budowanie**: `build_sim` / `build_device` (NIE `xcodebuild` przez Bash)
- **Testowanie**: `test_sim` / `test_device` (NIE `xcodebuild test` przez Bash)
- **Symulatory**: `list_sims`, `boot_sim`, `open_sim` (NIE `xcrun simctl` przez Bash)
- **Debugowanie**: `debug_attach_sim`, `debug_stack`, `debug_variables`
- **Dokumentacja Apple**: `DocumentationSearch` (NIE WebSearch dla API Apple)
- **Weryfikacja Swift**: `ExecuteSnippet` (NIE `swift` przez Bash)
- **Podglądy**: `RenderPreview` do bezgłowego sprawdzania SwiftUI
MCP zwraca ustrukturyzowane dane JSON. Bash zwraca nieustrukturyzowany tekst.
Ustrukturyzowane dane oznaczają mniejsze zużycie tokenów i lepszą diagnostykę błędów.
Ta wskazówka zapewnia, że agent sięga najpierw po narzędzia MCP. Bez niej zaobserwujemy, jak agent konstruuje długie polecenia xcodebuild przez Bash, zużywa tysiące tokenów kontekstu na parsowanie wyniku, a niekiedy błędnie identyfikuje faktyczny błąd.
Wzorce CLAUDE.md dla projektów iOS
CLAUDE.md to najważniejszy plik w projekcie przy programowaniu wspomaganym przez agenta. Jest to dokument wdrożeniowy agenta — różnica między nowym pracownikiem, który przeczytał dokumentację architektury, a takim, który zgaduje.
Każdy projekt iOS, który prowadzę, ma CLAUDE.md. Oto wzorce, które sprawdzają się w praktyce, zebrane z wszystkich 8 aplikacji.
Niezbędne sekcje
Każdy CLAUDE.md dla iOS potrzebuje tych sześciu sekcji. Wszystko inne jest opcjonalne.
1. Tożsamość projektu
# Return - Zen Focus Timer
**Bundle ID:** `com.941apps.Return`
**Target:** iOS 26+ / macOS Tahoe / watchOS 26+ / tvOS 26+
**Architecture:** SwiftUI with @Observable pattern, companion Watch and TV apps
**Swift version:** 6.2
**Minimum deployment:** iOS 26.0
Dlaczego to ma znaczenie: agent musi znać docelową wersję systemu, zanim napisze jakikolwiek kod. Agent celujący w iOS 17 użyje NavigationView i @ObservedObject. Agent celujący w iOS 26 użyje NavigationStack i @Observable. Bundle ID ma znaczenie dla uprawnień i konfiguracji HealthKit. Wersja Swift determinuje model współbieżności (async/await kontra handlery zakończenia, ścisła współbieżność kontra łagodna).
2. Struktura plików z adnotacjami przeznaczenia
## File Structure
Return/ ├── ReturnApp.swift # App entry, dark mode enforcement ├── ContentView.swift # Main timer view with theme backgrounds ├── TimerManager.swift # Timer state, logic, and repeat handling ├── AudioManager.swift # Sound playback with AVAudioPlayer ├── Settings.swift # Centralized settings with validation ├── SettingsSheet.swift # Settings UI ├── HealthKitManager.swift # Mindful session logging + cross-device sync ├── LiveActivityManager.swift # Lock Screen/Dynamic Island ├── Theme.swift # Theme definitions ├── ThemeManager.swift # Theme state management ├── VideoBackgroundView.swift # AVPlayer video backgrounds ├── GlassTextShape.swift # Core Text glyph paths for glass effect ├── GlassTimerText.swift # Timer text with glass material └── Constants.swift # App constants
Komentarze inline po każdej nazwie pliku nie są dekoracją. Są to najwyżej dźwigniowa dokumentacja, jaką można napisać. Gdy agent decyduje, gdzie dodać nową funkcję, te adnotacje kierują go do właściwego pliku za pierwszym razem, zamiast zmuszać do czytania każdego pliku w celu zrozumienia układu projektu.
Antywzorzec: Wylistowanie plików bez adnotacji. TimerManager.swift nie mówi agentowi nic o tym, czy obsługuje stan, UI, czy jedno i drugie. TimerManager.swift # Timer state, logic, and repeat handling mówi dokładnie, co tam należy, a co nie.
3. Polecenia budowania i testowania
## Build & Test
Build for iOS simulator:
```bash
xcodebuild -scheme Return -destination 'platform=iOS Simulator,name=iPhone 16 Pro' build
Run tests:
xcodebuild -scheme Return -destination 'platform=iOS Simulator,name=iPhone 16 Pro' test
Run tvOS tests:
xcodebuild -scheme ReturnTV -destination 'platform=tvOS Simulator,name=Apple TV' test
Prefer MCP tools (build_sim, test_sim) over these raw commands.
MCP returns structured JSON with categorized errors.
Warto umieszczać surowe polecenia, mimo że agent powinien preferować MCP. Surowe polecenia służą jako dokumentacja zapasowa i jawnie wskazują nazwy schematów oraz destynacje.
#### 4. Kluczowe wzorce i reguły
```markdown
## Key Patterns
### Observable Architecture
- ALL view models use `@Observable` (NEVER `ObservableObject`)
- ALL navigation uses `NavigationStack` (NEVER `NavigationView`)
- State management via `@Observable` classes with `@MainActor` isolation
### Settings Pattern
- Centralized `Settings.shared` singleton
- All settings bounded to valid ranges with validation
- Sound names validated against whitelist
- Thread-safe access via @MainActor
### Audio System
- `AVAudioPlayer` with `.playback` category (plays in silent mode)
- Silent audio loop for background execution
- Bell playback with completion callbacks and token-based staleness
Te wzorce zapobiegają wprowadzaniu niespójności przez agenta. Bez jawnej dokumentacji wzorców agent niekiedy użyje ObservableObject w jednym pliku i @Observable w drugim, lub stworzy nowy mechanizm ustawień zamiast wykorzystać istniejący singleton Settings.shared.
5. Rzeczy, których agent nigdy nie powinien robić
## Rules
- **NEVER modify .pbxproj files** — create Swift files, then I will add them to Xcode manually
- **NEVER modify .xcodeproj/ contents directly**
- **NEVER add new package dependencies** without asking first
- **NEVER change the deployment target**
- **NEVER modify entitlements files** unless explicitly asked
- **NEVER use NavigationView** — always NavigationStack
- **NEVER use ObservableObject** — always @Observable
- **NEVER use @StateObject** — always @State with @Observable
Jawne zakazy są skuteczniejsze niż niejawne oczekiwania. Agent przestrzega ograniczeń negatywnych bardziej niezawodnie niż pozytywnych sugestii, ponieważ mają charakter binarny (rób to / nie rób tego), a nie heurystyczny (preferuj to / czasem użyj tamtego).
6. Kontekst specyficzny dla frameworka
Ta sekcja różni się w zależności od aplikacji. Należy ją umieścić dla każdego frameworka, który ma nieoczywistą konfigurację:
Dla aplikacji HealthKit:
## HealthKit Configuration
- Entitlement: `com.apple.developer.healthkit`
- Info.plist keys:
- `NSHealthShareUsageDescription`: "Return reads your mindful minutes..."
- `NSHealthUpdateUsageDescription`: "Return logs meditation sessions..."
- Category types: `HKCategoryType(.mindfulSession)`
- Authorization checked on every write (user can revoke at any time)
- HealthKit is unavailable on tvOS — guard with `#if canImport(HealthKit)`
Dla aplikacji SwiftData:
## SwiftData Models
### Model Relationships
- `GroceryList` has many `GroceryItem` (cascade delete)
- `GroceryItem` belongs to one `GroceryList`
- `GroceryItem` has optional `Category`
### Model Container Setup
- Configured in App struct with `modelContainer(for:)`
- Schema versioning: currently V2
- Migration plan: `GroceryMigrationPlan` handles V1 → V2
### Queries
- `@Query(sort: \GroceryItem.name)` for sorted fetches
- `@Query(filter: #Predicate { !$0.isCompleted })` for active items
- Always use `@Query` in views, `modelContext.fetch()` in managers
Dla aplikacji SpriteKit:
## SpriteKit Scene Hierarchy
GameScene (SKScene) ├── backgroundLayer (SKNode, zPosition: -100) │ └── StarfieldNode (custom, parallax scrolling) ├── gameLayer (SKNode, zPosition: 0) │ ├── playerShip (PlayerNode, zPosition: 10) │ ├── enemyContainer (SKNode, zPosition: 5) │ └── bulletPool (SKNode, zPosition: 8) ├── effectsLayer (SKNode, zPosition: 50) │ └── ParticleManager (manages explosion/trail emitters) └── hudLayer (SKNode, zPosition: 100) ├── scoreLabel (SKLabelNode) └── healthBar (HealthBarNode)
- Physics categories defined in `PhysicsCategory.swift` as bitmasks
- Contact detection via `didBegin(_ contact:)` on GameScene
- Bullet pooling: pre-allocate 50, recycle via `removeFromParent()` + re-add
Dla aplikacji Metal:
## Metal Pipeline
- Render pipeline: `MetalView` → `Renderer` → `ShaderLibrary`
- Compute pipeline: `AudioAnalyzer` → compute shader → texture output
- Shared uniforms struct: `Uniforms` in `ShaderTypes.h` (bridged to Swift)
- Frame timing: `CADisplayLink` drives render loop
- Buffer triple-buffering: 3 in-flight frames with semaphore
### Shader Files
- `Shaders.metal` — Main render shaders (vertex + fragment)
- `Compute.metal` — Audio analysis compute kernel
- `PostProcess.metal` — Bloom and color grading
### DO NOT modify Metal shaders without testing on device.
Simulator Metal is not representative of device GPU behavior.
Prawdziwy CLAUDE.md: Banana List (SwiftUI + SwiftData + iCloud + serwer MCP)
Oto opatrzony komentarzami przykład pokazujący, jak wszystkie sześć sekcji współgrają ze sobą w średnio złożonej aplikacji. To wzorzec CLAUDE.md, którego używam w Banana List — 53-plikowej aplikacji do list zakupów z synchronizacją iCloud i niestandardowym serwerem MCP, który udostępnia dane aplikacji dla Claude Desktop:
# Banana List - Grocery List App
**Bundle ID:** `com.941apps.BananaList`
**Target:** iOS 26+
**Architecture:** SwiftUI + SwiftData + iCloud Drive sync
**Swift version:** 6.2
**Minimum deployment:** iOS 26.0
## Core Features
- Grocery lists with items, categories, and quantities
- iCloud Drive sync via SwiftData CloudKit integration
- Custom MCP server exposing list data to Claude Desktop
- Liquid Glass design system
- Haptic feedback on interactions
- Share sheets for list sharing
## Struktura plików
BananaList/ ├── BananaListApp.swift # App entry, model container setup ├── Models/ │ ├── GroceryList.swift # @Model: list with name, items, color │ ├── GroceryItem.swift # @Model: item with name, quantity, category, isCompleted │ ├── Category.swift # @Model: user-defined categories │ └── SampleData.swift # Preview and test data ├── Views/ │ ├── ListsView.swift # Main list of grocery lists │ ├── ListDetailView.swift # Items within a list │ ├── ItemRow.swift # Single item row with swipe actions │ ├── AddItemSheet.swift # New item form │ ├── CategoryPicker.swift # Category selection with create-new │ └── SettingsView.swift # App settings ├── Managers/ │ ├── CloudSyncManager.swift # iCloud Drive sync status and conflict resolution │ └── HapticManager.swift # UIImpactFeedbackGenerator wrapper ├── MCP/ │ ├── MCPServer.swift # MCP server for Claude Desktop integration │ ├── ListTools.swift # MCP tools: list CRUD operations │ └── ItemTools.swift # MCP tools: item CRUD operations └── Extensions/ ├── Color+Extensions.swift # Custom color definitions └── View+Extensions.swift # Reusable view modifiers
## Modele SwiftData
### Relacje
- `GroceryList` posiada wiele obiektów `GroceryItem` (usuwanie kaskadowe)
- `GroceryItem` należy do jednego `GroceryList` (wymagane)
- `GroceryItem` posiada opcjonalną `Category`
- `Category` posiada wiele obiektów `GroceryItem` (nullify przy usuwaniu)
### Konfiguracja kontenera
```swift
@main
struct BananaListApp: App {
var body: some Scene {
WindowGroup {
ListsView()
}
.modelContainer(for: [GroceryList.self, GroceryItem.self, Category.self])
}
}
Wzorce zapytań
- Listy:
@Query(sort: \GroceryList.name) var lists: [GroceryList] - Aktywne elementy:
@Query(filter: #Predicate { !$0.isCompleted }) - Według kategorii: filtrowanie w pamięci po pobraniu (ograniczenia predykatów SwiftData)
Budowanie i testowanie
xcodebuild -scheme BananaList -destination 'platform=iOS Simulator,name=iPhone 16 Pro' build
xcodebuild -scheme BananaList -destination 'platform=iOS Simulator,name=iPhone 16 Pro' test
Warto korzystać z narzędzi MCP (build_sim, test_sim) zamiast surowych poleceń.
Kluczowe wzorce
Observable + SwiftData
- Klasy SwiftData z makrem
@Modelsą automatycznie Observable - NIE NALEŻY dodawać
@Observabledo klas@Model(nadmiarowe, powoduje ostrzeżenia) - Należy używać
@Bindabledo dwukierunkowych powiązań z właściwościami modelu w formularzach - Należy używać
@Queryw widokach,modelContext.fetch()w kodzie poza widokami
Synchronizacja iCloud
- Automatyczna dzięki integracji SwiftData z CloudKit
- Rozwiązywanie konfliktów: ostatni zapis wygrywa (domyślne zachowanie CloudKit)
- Status synchronizacji dostępny przez
CloudSyncManager.shared.syncState - Testowanie synchronizacji wymaga uruchomienia na dwóch symulatorach z tym samym kontem iCloud
Architektura serwera MCP
- Działa jako lokalny serwer WebSocket na porcie 8765
- Udostępnia 6 narzędzi: listAll, getList, createList, addItem, completeItem, deleteItem
- Claude Desktop łączy się przez konfigurację MCP w
~/.config/claude-desktop/config.json
Zasady
- NIGDY nie modyfikować zawartości .pbxproj ani .xcodeproj
- NIGDY nie zmieniać schematu modelu bez aktualizacji SampleData.swift
- NIGDY nie używać
ObservableObject— modele SwiftData są już Observable - NIGDY nie używać
@StateObject— należy stosować@Statez klasami@Observable - NIGDY nie używać
NavigationView— zawszeNavigationStack - NIGDY nie dodawać makra
@Observabledo klas@Model - ZAWSZE używać
@Bindabledo powiązań formularzy z właściwościami modelu - ZAWSZE testować zmiany synchronizacji iCloud na dwóch instancjach symulatora
### Rzeczywisty CLAUDE.md: Reps (minimalna aplikacja SwiftData — 14 plików)
W przypadku małych projektów plik CLAUDE.md może być zwięzły. Oto wzorzec dla Reps — czternastoplikowego trackera treningów. Warto zauważyć, że nawet krótki CLAUDE.md obejmuje wszystkie sześć podstawowych sekcji:
```markdown
# Reps - Workout Tracking
**Bundle ID:** `com.941apps.Reps`
**Target:** iOS 26+
**Architecture:** SwiftUI + SwiftData
**Swift version:** 6.2
## File Structure
Reps/ ├── RepsApp.swift # App entry, model container ├── Models/ │ ├── Workout.swift # @Model: workout with exercises, date, duration │ ├── Exercise.swift # @Model: exercise with sets, reps, weight │ └── ExerciseTemplate.swift # @Model: saved exercise definitions ├── Views/ │ ├── WorkoutListView.swift # Main list of workouts │ ├── WorkoutDetailView.swift # Exercises within a workout │ ├── ExerciseRow.swift # Single exercise with inline editing │ ├── AddExerciseSheet.swift # Exercise selection from templates │ ├── NewWorkoutView.swift # Start new workout flow │ └── StatsView.swift # Progress charts and summaries ├── Managers/ │ └── WorkoutTimer.swift # Active workout timer └── Extensions/ └── Date+Extensions.swift # Formatting helpers
## Build & Test
```bash
xcodebuild -scheme Reps -destination 'platform=iOS Simulator,name=iPhone 16 Pro' build
xcodebuild -scheme Reps -destination 'platform=iOS Simulator,name=iPhone 16 Pro' test
SwiftData Relationships
Workouthas manyExercise(cascade delete)Exercisehas optionalExerciseTemplateExerciseTemplatestandalone (nullify on exercise delete)
Rules
- NEVER modify .pbxproj
- NEVER use ObservableObject — use @Observable
- NEVER use NavigationView — use NavigationStack
- @Model classes are already Observable — do not add @Observable macro
- Use @Bindable for form bindings to model properties
To zaledwie 40 linii CLAUDE.md dla projektu składającego się z 14 plików. Napisanie go zajmuje 10 minut, a oszczędza godziny nieporozumień agenta.
### Rzeczywisty CLAUDE.md: Starfield Destroyer (SpriteKit + Metal — 32 pliki)
Projekty gier wymagają więcej kontekstu specyficznego dla danego frameworka. Agent musi rozumieć graf sceny, kategorie fizyki oraz maszynę stanów gry:
```markdown
# Starfield Destroyer - Space Shooter
**Bundle ID:** `com.941apps.StarfieldDestroyer`
**Target:** iOS 26+
**Architecture:** SpriteKit + Metal post-processing + Game Center
**Swift version:** 6.2
## Game Overview
99 levels across 3 galaxies. 8 unlockable ships with different stats.
Game Center leaderboards and achievements. Metal shader post-processing
for bloom and screen effects.
## File Structure
StarfieldDestroyer/ ├── StarfieldDestroyerApp.swift # App entry, Game Center auth ├── GameScene.swift # Main game scene, update loop ├── MenuScene.swift # Title screen, ship selection ├── Entities/ │ ├── PlayerShip.swift # Player node with physics, weapons, shields │ ├── EnemyShip.swift # Enemy base class with AI behaviors │ ├── Bullet.swift # Bullet pool node │ ├── PowerUp.swift # Collectible power-ups │ └── Boss.swift # Boss enemies (levels 33, 66, 99) ├── Systems/ │ ├── LevelManager.swift # Level progression, wave spawning │ ├── PhysicsCategory.swift # UInt32 bitmask categories │ ├── CollisionHandler.swift # Contact delegate methods │ ├── ScoreManager.swift # Score tracking, multipliers │ ├── ParticleManager.swift # Explosion, trail, shield emitters │ └── AudioManager.swift # Sound effects, background music ├── UI/ │ ├── HUDNode.swift # Score, health, level display │ ├── ShipSelectView.swift # SwiftUI ship selection (UIHostingController) │ ├── GameOverView.swift # Game over screen with score submission │ └── PauseMenu.swift # Pause overlay ├── Metal/ │ ├── MetalRenderer.swift # Post-processing render pipeline │ ├── BloomShader.metal # Bloom post-process effect │ └── ShaderTypes.h # Shared uniforms (bridging header) ├── Data/ │ ├── ShipData.swift # 8 ship definitions (speed, damage, shields) │ ├── LevelData.swift # 99 level configurations │ └── AchievementData.swift # Game Center achievement definitions └── GameCenterManager.swift # Leaderboard/achievement submission
## SpriteKit Scene Hierarchy
GameScene (SKScene) ├── backgroundLayer (zPosition: -100) │ └── StarfieldNode (parallax scrolling, 3 layers) ├── gameLayer (zPosition: 0) │ ├── playerShip (zPosition: 10) │ ├── enemyContainer (zPosition: 5) │ ├── bulletPool (zPosition: 8) — pre-allocated 50 bullets │ └── powerUpContainer (zPosition: 3) ├── effectsLayer (zPosition: 50) │ └── ParticleManager (explosion + trail emitters) └── hudLayer (zPosition: 100) ├── scoreLabel (SKLabelNode) ├── healthBar (custom SKShapeNode) └── levelLabel (SKLabelNode)
## Physics Categories
```swift
struct PhysicsCategory {
static let none: UInt32 = 0
static let player: UInt32 = 0b1 // 1
static let enemy: UInt32 = 0b10 // 2
static let bullet: UInt32 = 0b100 // 4
static let powerUp: UInt32 = 0b1000 // 8
static let shield: UInt32 = 0b10000 // 16
static let bossBullet:UInt32 = 0b100000 // 32
}
// Contact pairs:
// player + enemy → damage
// player + powerUp → collect
// bullet + enemy → destroy
// player + bossBullet → damage
Maszyna stanów gry
.menu → .playing → .paused → .playing
→ .gameOver → .menu
→ .bossIntro → .playing
→ .levelComplete → .playing (next level)
Post-processing Metal
- Shader bloom:
BloomShader.metal— wieloprzebiegowe rozmycie gaussowskie + mieszanie addytywne - Uniformy:
PostProcessUniforms { float intensity; float threshold; float2 resolution; } - Stosowany po wyrenderowaniu każdej klatki przez SpriteKit za pośrednictwem
SKView.presentScene(:transition:) - NIE NALEŻY modyfikować shaderów Metal bez testowania na urządzeniu
Budowanie i testowanie
xcodebuild -scheme StarfieldDestroyer -destination 'platform=iOS Simulator,name=iPhone 16 Pro' build
xcodebuild -scheme StarfieldDestroyer -destination 'platform=iOS Simulator,name=iPhone 16 Pro' test
## Zasady
- NIGDY nie modyfikować .pbxproj
- NIGDY nie modyfikować masek bitowych PhysicsCategory (powoduje uszkodzenie całego wykrywania kolizji)
- NIGDY nie zmieniać kolejności z-ordering w hierarchii sceny bez zrozumienia kolejności renderowania
- NIGDY nie modyfikować ShaderTypes.h bez aktualizacji odniesień zarówno po stronie Swift, jak i Metal
- Nowych wrogów należy dodawać poprzez tworzenie podklas EnemyShip, nie poprzez modyfikację tej klasy
- Pula pocisków: recykling poprzez removeFromParent() + ponowne dodanie, nigdy nie alokować nowych
- Game Center: zawsze sprawdzać isAuthenticated przed przesyłaniem wyników
Rzeczywisty CLAUDE.md: amp97 (Metal + wizualizacja audio — 41 plików)
Projekty Metal wymagają najwięcej kontekstu specyficznego dla frameworka, ponieważ agenci nie mogą zweryfikować wizualnych wyników:
# amp97 - Audio Visualizer
**Bundle ID:** `com.941apps.amp97`
**Target:** iOS 26+
**Architecture:** Metal render pipeline + AVAudioEngine analysis
**Swift version:** 6.2
## Architecture
Audio Input (microphone/file) → AVAudioEngine tap → FFT (vDSP) → Frequency/amplitude buffers → Metal compute shader (analysis) → Metal render pipeline (visualization) → CADisplayLink (60fps) → MTKView
## File Structure
amp97/ ├── amp97App.swift # App entry ├── Audio/ │ ├── AudioEngine.swift # AVAudioEngine setup, tap installation │ ├── FFTProcessor.swift # vDSP FFT, frequency bin extraction │ ├── AudioBuffer.swift # Ring buffer for audio data │ └── MicrophoneManager.swift # Microphone permission, session config ├── Rendering/ │ ├── MetalView.swift # MTKView wrapper for SwiftUI │ ├── Renderer.swift # Main render loop, pipeline state │ ├── ShaderLibrary.swift # Compiled shader management │ ├── BufferManager.swift # Triple-buffered uniform updates │ └── TextureManager.swift # Offscreen render targets ├── Shaders/ │ ├── Shaders.metal # Vertex + fragment shaders │ ├── AudioCompute.metal # Audio analysis compute kernel │ ├── PostProcess.metal # Bloom, color grading │ └── ShaderTypes.h # Shared uniforms (bridging header) ├── Visualizations/ │ ├── WaveformViz.swift # Oscilloscope-style waveform │ ├── SpectrumViz.swift # Frequency spectrum bars │ ├── CircularViz.swift # Radial visualization │ └── VizSelector.swift # Visualization switching ├── Views/ │ ├── MainView.swift # Full-screen viz with overlays │ ├── ControlsOverlay.swift # Play/pause, viz selection, gain │ └── SettingsView.swift # Audio source, sensitivity └── Extensions/ ├── SIMD+Extensions.swift # Vector math helpers └── Color+Metal.swift # UIColor → float4 conversion
## Metal Pipeline
### Uniforms (ShaderTypes.h)
```c
typedef struct {
float time;
float2 resolution;
float audioLevel; // 0.0-1.0 RMS amplitude
float frequencyBins[64]; // FFT output, normalized
float4x4 transform;
} Uniforms;
Render Pipeline
- Compute pass: AudioCompute.metal processes FFT data → texture
- Render pass: Shaders.metal reads texture + uniforms → visualization
- Post-process pass: PostProcess.metal applies bloom → final output
Buffer Management
- Triple buffering with DispatchSemaphore(value: 3)
- Uniforms updated per-frame on CPU, consumed by GPU 1-2 frames later
- Audio data ring buffer: 4096 samples, lock-free single producer/consumer
Rules
- NEVER modify ShaderTypes.h without updating BOTH Swift and Metal sides
- NEVER exceed 64 frequency bins (fixed buffer size in shader)
- NEVER test Metal visual output in simulator — device only
- NEVER modify the audio engine tap format (48kHz, mono, float32)
- Triple buffer discipline: always signal semaphore in completion handler
- Audio session: .playAndRecord category with .defaultToSpeaker option
### Skalowanie CLAUDE.md wraz z rozmiarem projektu
Odpowiedni poziom szczegółowości zależy od liczby plików i złożoności frameworka:
| Rozmiar projektu | Głębokość CLAUDE.md | Przykład |
|-------------|----------------|---------|
| **Mały (< 20 plików)** | Tożsamość + lista plików + zasady | Reps (14 plików): podstawowe wzorce SwiftData, polecenia budowania, zakazy |
| **Średni (20-40 plików)** | + kontekst frameworka + kluczowe wzorce | TappyColor (30 plików): hierarchia scen SpriteKit, kategorie fizyki, pętla gry |
| **Duży (40+ plików)** | + diagramy architektury + mapy zależności + informacje o wielu celach | Return (63 pliki): architektura wieloplatformowa, diagram synchronizacji sesji, różnice między platformami |
| **Specjalistyczny (Metal/GPU)** | + diagramy potoku + definicje współdzielonych typów + układy buforów | amp97 (41 plików): etapy potoku renderowania, struktura uniformów, zarządzanie buforami |
Koszt nadmiernej dokumentacji jest bliski zeru (agent pomija to, czego nie potrzebuje). Koszt niedostatecznej dokumentacji jest wysoki (agent wymyśla wzorce kolidujące z istniejącą bazą kodu).
### Lista kontrolna CLAUDE.md
Poniższa lista kontrolna przydaje się podczas tworzenia lub audytu CLAUDE.md dla projektu iOS:
- [ ] Określony Bundle ID i docelowa wersja systemu
- [ ] Wskazana wersja Swift i wzorzec architektury
- [ ] Struktura plików z adnotacjami opisującymi przeznaczenie
- [ ] Polecenie budowania z prawidłowym schematem i miejscem docelowym
- [ ] Polecenie testowania z prawidłowym schematem i miejscem docelowym
- [ ] Zanotowana preferencja MCP („preferuj build_sim zamiast xcodebuild")
- [ ] Zasada @Observable (nigdy ObservableObject)
- [ ] Zasada NavigationStack (nigdy NavigationView)
- [ ] Zakaz modyfikacji .pbxproj
- [ ] Kontekst specyficzny dla frameworka (uprawnienia HealthKit, relacje SwiftData, hierarchia SpriteKit, potok Metal)
- [ ] Udokumentowane strażniki dostępności platformy (#if canImport, #if os)
- [ ] Udokumentowane kluczowe singletony i współdzielone wzorce
- [ ] Zanotowane znane ograniczenia i pułapki
---
## Pierwsza sesja z agentem
Po skonfigurowaniu MCP i umieszczeniu CLAUDE.md w projekcie, oto przewodnik po skutecznej pierwszej sesji. Przykład wykorzystuje Claude Code CLI, ale przepływ pracy ma zastosowanie do każdego środowiska uruchomieniowego.
### Krok 1: Weryfikacja, czy agent widzi projekt
You: Summarize this project. What scheme should I build with?
Claude: [reads CLAUDE.md] [calls discover_projs via MCP] [calls list_schemes via MCP]
This is Return, a zen meditation timer for iOS 26+, watchOS, and tvOS.
Available schemes: Return, ReturnWatch, ReturnTV, ReturnTests.
Primary scheme for iOS: Return.
Jeśli agent nie odwołuje się do treści CLAUDE.md, należy sprawdzić, czy plik znajduje się w katalogu głównym projektu (w tym samym katalogu co `.xcodeproj` lub `Package.swift`).
### Krok 2: Kontrolny build
You: Build the Return scheme for iOS simulator and report results.
Claude: [calls list_sims — finds iPhone 16 Pro on iOS 26.2] [calls boot_sim — boots the simulator] [calls build_sim — builds the project]
Build succeeded. 63 source files compiled.
2 warnings:
- HomeView.swift:132 — UIScreen.main deprecated in iOS 26.0
- LogWaterIntent.swift:61 — Result of try? is unused
0 errors.
### Krok 3: Uruchomienie testów
You: Run all tests and report pass/fail.
Claude: [calls test_sim]
12 tests executed:
✓ TimerManagerTests (5/5 passed)
✓ SettingsTests (4/4 passed)
✓ ConstantsTests (3/3 passed)
All tests passed.
### Krok 4: Implementacja funkcji
You: Add a new “Rain” theme to the theme system. Follow the existing pattern in Theme.swift and ThemeManager.swift. Include a rain ambient sound. Build and test after implementation.
Claude: [reads Theme.swift — understands Theme struct pattern] [reads ThemeManager.swift — understands theme registration] [reads existing theme definitions] [adds Rain theme to Theme.swift following existing pattern] [registers Rain theme in ThemeManager.swift] [calls build_sim — build succeeds] [calls test_sim — all tests pass]
Added Rain theme:
- Theme.swift: new `static let rain` with video, cover, ambient
- ThemeManager.swift: added to `allThemes` array
- Build: success (0 errors, 2 existing warnings)
- Tests: 12/12 passed
Note: You'll need to add rain_ambient.wav to the project
and add the new Theme.swift changes to the Xcode target manually
(I did not modify .pbxproj).
Uwaga agenta o niemodyfikowaniu .pbxproj jest bezpośrednim rezultatem zasad zapisanych w CLAUDE.md. Bez tej zasady agent próbowałby zmodyfikować plik projektu, co prawdopodobnie doprowadziłoby do jego uszkodzenia.
---
## Co agenci robią dobrze w iOS
Oto zadania, w których agenci konsekwentnie generują poprawny, produkcyjny kod wymagający minimalnej weryfikacji człowieka.
### Widoki i modyfikatory SwiftUI
Agenci wykazują głębokie rozpoznawanie wzorców składni deklaratywnej SwiftUI. Kompozycja widoków, łańcuchy modyfikatorów, wiązania stanu i układ — wszystko to dobrze odpowiada danym treningowym agenta, ponieważ powierzchnia API SwiftUI jest dobrze udokumentowana, a wzorce są wysoce spójne.
**Gdzie agenci się sprawdzają:**
- Tworzenie nowych widoków na podstawie opisu („utwórz arkusz ustawień z przełącznikami dla X, Y, Z")
- Stosowanie łańcuchów modyfikatorów (`.glassEffect()`, `.sensoryFeedback()`, `.navigationTitle()`)
- Konwersja między wzorcami układu (VStack na LazyVGrid, List na ScrollView)
- Implementacja wiązań formularzy `@Bindable` z modelami SwiftData
- Tworzenie dostawców podglądu z przykładowymi danymi
**Przykładowy prompt, który daje doskonałe wyniki:**
Create a SettingsView that matches the existing pattern in SettingsSheet.swift. Include toggles for: - Enable haptic feedback (Settings.shared.hapticsEnabled) - Enable HealthKit logging (Settings.shared.healthKitEnabled) - Show session history (navigation link to SessionHistoryView)
Use Liquid Glass styling with .glassEffect() on section backgrounds. Follow the @Observable pattern, not ObservableObject.
Precyzja ma znaczenie. „Create a settings view" generuje ogólnikowy wynik. „Create a SettingsView that matches the existing pattern in SettingsSheet.swift" generuje wynik spójny z bazą kodu.
### Modele i zapytania SwiftData
Agenci niezawodnie obsługują makro `@Model` SwiftData, relacje oraz wzorce `@Query`. Deklaratywna natura frameworka (podobna do Django ORM czy SQLAlchemy) dobrze odpowiada wzorcom, które agent widział w wielu bazach kodu.
**Gdzie agenci się sprawdzają:**
- Definiowanie klas `@Model` z relacjami
- Pisanie `@Query` z deskryptorami sortowania i predykatami
- Implementacja operacji CRUD przez `modelContext`
- Plany migracji między wersjami schematu
- Dane podglądowe i zestawy testowe
**Gdzie agenci potrzebują wskazówek:**
- Złożone wyrażenia `#Predicate` (DSL predykatów SwiftData ma ograniczenia, o których agent nie zawsze wie — warto udokumentować znane ograniczenia w CLAUDE.md)
- Konfiguracja synchronizacji CloudKit (automatyczna przez SwiftData, ale agent może próbować zaimplementować ręczną synchronizację)
### Testy jednostkowe
Testy jednostkowe pisane przez agentów są konsekwentnie wysokiej jakości w projektach iOS. Agent rozumie wzorce XCTest, asynchroniczne metody testowe oraz cykl życia setUp/tearDown.
Write unit tests for TimerManager covering: 1. Initial state is .stopped 2. start() transitions to .running 3. pause() transitions to .paused 4. reset() returns to .stopped with original duration 5. Timer counts down correctly (test with 3-second duration)
Agent generuje dobrze ustrukturyzowane przypadki testowe XCTest z `setUp()` i `tearDown()`, odpowiednimi asercjami oraz obsługą asynchroniczności dla testów opartych na timerach.
### Refaktoryzacja i stosowanie wzorców
Agenci doskonale radzą sobie z mechaniczną refaktoryzacją: ekstrakcją widoków do komponentów, konwersją `ObservableObject` na `@Observable`, migracją z `NavigationView` na `NavigationStack` oraz stosowaniem spójnych wzorców w wielu plikach.
Refactor all views in the Views/ directory to use @Observable instead of ObservableObject. Update @StateObject to @State, @ObservedObject to direct property access, and @Published to plain properties.
Agent metodycznie przechodzi przez każdy plik, poprawnie stosuje transformację i zachowuje istniejącą funkcjonalność. To praca o dużej dźwigni — refaktoryzacja, która ręcznie zajęłaby godzinę, kończy się w kilka minut z niemal idealną dokładnością.
### Diagnozowanie błędów kompilacji przez MCP
Dzięki ustrukturyzowanemu wyjściu MCP agenci diagnozują błędy kompilacji szybciej niż większość programistów. Agent odczytuje JSON błędów, identyfikuje dokładny plik i linię, rozumie komunikat o błędzie i stosuje poprawkę — często w jednym kroku.
**Błędy naprawiane autonomicznie przez agentów:**
- Brakujące importy
- Niezgodności typów
- Braki w zgodności z protokołami
- Użycie przestarzałego API (z zamiennikiem)
- Brakujące wymagane parametry inicjalizatora
- Naruszenia kontroli dostępu
**Błędy wymagające pomocy:**
- Niejednoznaczne rozwiązywanie typów (wiele modułów definiuje ten sam typ)
- Złożone błędy ograniczeń generycznych
- Błędy rozwijania makr (agent nie widzi rozwiniętego wyjścia makra)
### Zarządzanie symulatorem
Agenci dobrze obsługują cykl życia symulatora przez MCP:
Boot an iPhone 16 Pro simulator on iOS 26, install the app, and take a screenshot.
Agent wywołuje `list_sims`, aby znaleźć dostępne środowiska uruchomieniowe, `boot_sim`, aby uruchomić symulator, `build_sim`, aby zbudować i zainstalować aplikację, oraz `screenshot`, aby wykonać zrzut ekranu — wszystko poprzez ustrukturyzowane wywołania MCP.
---
## Czego agenci nie potrafią w kontekście iOS
Uczciwe podsumowanie obszarów, w których agenci zawodzą. Znajomość tych ograniczeń pozwala uniknąć frustracji i zmarnowanych tokenów.
### Modyfikacje pliku .pbxproj — NIGDY
To najważniejsza zasada w pracy z agentami przy tworzeniu aplikacji iOS. Plik `.pbxproj` to konfiguracja projektu Xcode — ustrukturyzowany plik tekstowy z odniesieniami UUID, listami faz budowania i przynależnością do celów. Nominalnie jest czytelny dla człowieka, lecz praktycznie nieparsowalny dla agentów AI.
**Dlaczego agenci nie radzą sobie z .pbxproj:**
- Plik używa niestandardowego formatu (nie JSON, nie YAML, nie XML) z pozycyjnym znaczeniem elementów
- Każdy wpis jest powiązany krzyżowo przez UUID — dodanie pliku wymaga spójnej aktualizacji 3–5 różnych sekcji
- Pojedynczy błędny znak uszkadza cały plik projektu
- Rozwiązywanie konfliktów scalania dla .pbxproj w Xcode jest i tak kruche — edycje agentów to pogarszają
**Co się dzieje, gdy agent edytuje .pbxproj:**
1. Edycja pozornie się udaje (agent raportuje „plik zaktualizowany")
2. Xcode odmawia otwarcia projektu („Plik projektu jest uszkodzony")
3. Odzyskiwanie z historii git zajmuje 15–60 minut
4. Uczysz się dodawać hook PreToolUse (zobacz [Hooki](#hooks-for-ios-development))
**Przepływ pracy:** Agent tworzy pliki Swift. Dodawanie ich do projektu Xcode odbywa się ręcznie (przeciągnięcie do Xcode lub File > Add Files). Zajmuje to 5 sekund na plik i zapobiega godzinom odzyskiwania.
**W przypadku projektów Swift Package Manager:** To ograniczenie jest mniej dotkliwe. `Package.swift` to standardowy plik Swift, który agenci mogą niezawodnie edytować. Jeśli projekt korzysta wyłącznie z SPM (bez .xcodeproj), agent może zarządzać pełną strukturą projektu.
### Złożone edycje Interface Builder / Storyboard
Jeśli projekt wykorzystuje Interface Builder (pliki `.xib`) lub Storyboardy (pliki `.storyboard`), agenci nie są w stanie sensownie ich edytować. To pliki XML z automatycznie generowanymi UUID, odniesieniami do ograniczeń i połączeniami outletów, zaprojektowane do edycji wizualnej, nie tekstowej.
**Rozwiązanie:** Nowe widoki należy tworzyć wyłącznie w SwiftUI. Jeśli projekt zawiera starsze pliki Interface Builder, lepiej je zostawić i budować nowe UI w SwiftUI.
### Optymalizacja wydajności
Agenci piszą poprawny kod, ale niekoniecznie wydajny. Nie potrafią profilować aplikacji, identyfikować wąskich gardeł ani mierzyć liczby klatek na sekundę. Optymalizacja wydajności wymaga:
1. Profilowania w Instruments (narzędzie wizualne, niedostępne dla agentów)
2. Znajomości charakterystyki GPU/CPU konkretnego urządzenia
3. Iteracyjnych zmian opartych na pomiarach
**Gdzie to się objawia:**
- Optymalizacja shaderów Metal (agent pisze poprawny Metal, ale nie może zmierzyć czasu klatki GPU)
- Złożoność ciała widoków SwiftUI (agent tworzy głęboko zagnieżdżone widoki powodujące nadmiarowe przerysowywanie)
- Optymalizacja zapytań Core Data / SwiftData (agent pisze poprawne zapytania, które mogą być wolne na dużych zbiorach danych)
**Rozwiązanie:** Agentów warto wykorzystywać do implementacji, profilować ręcznie za pomocą Instruments, a następnie zlecać agentowi konkretne optymalizacje, które zostały zidentyfikowane.
### Podpisywanie kodu i prowizjonowanie
Agenci nie potrafią debugować problemów z podpisywaniem kodu poza odczytaniem komunikatu o błędzie. Zarządzanie profilami prowizjonowania, tworzenie certyfikatów, konfiguracja uprawnień i przesyłanie do App Store to procesy wymagające ludzkiej obsługi, obejmujące portal Apple Developer, Keychain Access i interfejs podpisywania w Xcode.
**Co widzi agent:** „Signing for 'Return' requires a development team."
**Czego agent nie widzi:** Czy certyfikat wygasł, czy profil prowizjonowania obejmuje dane urządzenie, czy identyfikator pakietu odpowiada App ID ani czy plik uprawnień jest poprawny.
**Rozwiązanie:** Wszystkie kwestie podpisywania należy obsługiwać w zakładce Signing & Capabilities w Xcode. Nie warto prosić agentów o debugowanie problemów z podpisywaniem.
### Złożone debugowanie shaderów Metal
Agenci piszą składniowo poprawny Metal Shading Language (MSL), ale nie są w stanie zweryfikować wizualnego wyniku ani zdebugować problemów po stronie GPU. Shadery Metal wykonują się na GPU — agent nie dysponuje mechanizmem informacji zwrotnej o tym, czy shader generuje prawidłowe wyniki wizualne.
**Co agenci potrafią z Metal:**
- Pisać shadery wierzchołków i fragmentów na podstawie opisów
- Konfigurować potok renderowania Metal w Swift
- Tworzyć shadery obliczeniowe dla operacji równoległych na danych
- Naprawiać błędy kompilacji w plikach `.metal`
**Czego agenci nie potrafią z Metal:**
- Weryfikować wizualnej poprawności wyjścia shadera
- Debugować wydajności GPU (czas klatki, zajętość, przepustowość pamięci)
- Diagnozować artefaktów wizualnych (banding, problemy z precyzją, nieprawidłowa przestrzeń kolorów)
- Testować na różnych architekturach GPU (różnice w zachowaniu między seriami A i M)
**Rozwiązanie:** Shadery Metal należy testować na fizycznych urządzeniach. Implementacja Metal w Simulatorze nie jest reprezentatywna dla zachowania GPU na urządzeniu. Do wizualnego debugowania warto używać GPU Frame Capture w Xcode.
### Weryfikacja układu wizualnego
Agenci nie widzą interfejsu aplikacji. Piszą kod układu SwiftUI i mogą zweryfikować, czy się kompiluje, ale nie są w stanie stwierdzić, czy wynikowy ekran wygląda prawidłowo. Widok przesunięty o 10 pikseli od środka, z niewłaściwą grubością czcionki lub nakładającymi się elementami nie generuje żadnego błędu kompilacji i przechodzi wszystkie testy logiczne.
**Rozwiązanie:** Zmiany w UI należy weryfikować wizualnie. Warto korzystać z SwiftUI Previews w Xcode (lub `RenderPreview` przez Apple MCP do renderowania bezgłowego) w celu weryfikacji układu. Dla automatycznego wykrywania regresji wizualnych można rozważyć testowanie migawkowe za pomocą bibliotek takich jak swift-snapshot-testing.
---
## Hooki w kontekście programowania iOS
Hooki to polecenia powłoki, które wykonują się deterministycznie w określonych punktach przepływu pracy agenta. Stanowią mechanizm wymuszania — różnicę między „proszę nie edytować .pbxproj" (sugestią, którą agent może zignorować) a „nie można edytować .pbxproj" (twardą blokadą).
Informacje o systemie hooków można znaleźć w [Claude Code przewodniku po hookach](/blog/claude-code-hooks-tutorial). W tej sekcji omówiono wzorce hooków specyficzne dla iOS.
### PreToolUse: blokowanie zapisów do .pbxproj
Najważniejszy hook w każdym projekcie iOS. Blokuje agentowi możliwość zapisu do plików `.pbxproj`, katalogów `.xcodeproj/` oraz innych plików zarządzanych przez Xcode:
```json
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"command": "bash -c 'INPUT=$(cat); FP=$(echo \"$INPUT\" | jq -r \".tool_input.file_path // empty\"); if echo \"$FP\" | grep -qE \"\\.(pbxproj|xcworkspace|xib|storyboard)$|xcodeproj/|xcworkspace/\"; then echo \"BLOCKED: Do not modify Xcode project files. Create Swift files and add to Xcode manually.\" >&2; exit 2; fi'"
}
]
}
}
Należy umieścić to w pliku .claude/settings.json w katalogu głównym projektu lub w ~/.claude/settings.json w celu ochrony globalnej.
Jak to działa: Gdy agent próbuje użyć narzędzia Edit lub Write na pliku pasującym do wzorca, hook uruchamia się, wykrywa ścieżkę pliku, wypisuje ostrzeżenie na stderr i kończy działanie z kodem 2 (co blokuje użycie narzędzia). Agent otrzymuje komunikat o błędzie i dostosowuje swoje podejście.
Co przechwytuje:
- Bezpośrednie edycje .pbxproj
- Dowolny plik wewnątrz katalogów .xcodeproj/ lub .xcworkspace/
- Pliki Interface Builder (.xib, .storyboard)
PostToolUse: automatyczne formatowanie przy zapisie za pomocą SwiftFormat
Automatyczne formatowanie plików Swift za każdym razem, gdy agent je zapisuje lub edytuje:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"command": "bash -c 'INPUT=$(cat); FP=$(echo \"$INPUT\" | jq -r \".tool_input.file_path // empty\"); if echo \"$FP\" | grep -qE \"\\.swift$\"; then swiftformat \"$FP\" --quiet 2>/dev/null; fi'"
}
]
}
}
Wymagania: SwiftFormat musi być zainstalowany (brew install swiftformat).
Dlaczego to istotne: Agenci generują poprawny składniowo kod Swift, ale nie zawsze stosują konwencje formatowania. SwiftFormat normalizuje wcięcia, rozmieszczenie nawiasów klamrowych oraz kolejność importów. Hook automatycznego formatowania przy zapisie sprawia, że każdy plik Swift, który agent modyfikuje, jest automatycznie sformatowany, zanim zostanie wyświetlony.
Opcjonalnie: można dodać plik konfiguracyjny .swiftformat w katalogu głównym projektu, aby dostosować reguły formatowania:
# .swiftformat
--indent 4
--allman false
--stripunusedargs closure-only
--importgrouping testable-bottom
--header strip
PostToolUse: automatyczne uruchamianie SwiftLint
W przypadku korzystania z SwiftLint można uruchamiać go po każdej edycji pliku Swift:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"command": "bash -c 'INPUT=$(cat); FP=$(echo \"$INPUT\" | jq -r \".tool_input.file_path // empty\"); if echo \"$FP\" | grep -qE \"\\.swift$\"; then swiftlint lint --path \"$FP\" --quiet 2>/dev/null || true; fi'"
}
]
}
}
Fragment || true zapobiega blokowaniu agenta przez ostrzeżenia lintera. Jeśli naruszenia reguł lintera mają blokować działanie, należy go usunąć.
PostToolUse: automatyczne budowanie po zmianach
W celu uzyskania agresywnych pętli zwrotnych można uruchamiać budowanie po każdej zmianie pliku Swift:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"command": "bash -c 'INPUT=$(cat); FP=$(echo \"$INPUT\" | jq -r \".tool_input.file_path // empty\"); if echo \"$FP\" | grep -qE \"\\.swift$\"; then xcodebuild -scheme Return -destination \"platform=iOS Simulator,name=iPhone 16 Pro\" build 2>&1 | tail -5; fi'"
}
]
}
}
Uwaga: To kosztowna operacja. Każda edycja pliku wywołuje budowanie. Należy stosować oszczędnie — jest to najbardziej przydatne podczas sesji debugowania, gdy potrzebna jest natychmiastowa informacja zwrotna o budowaniu. W przypadku normalnego programowania lepiej pozwolić agentowi uruchamiać budowanie ręcznie za pomocą MCP, gdy będzie gotowy.
PreToolUse: blokowanie modyfikacji uprawnień
Ochrona pliku uprawnień (entitlements) przed przypadkowymi modyfikacjami przez agenta:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"command": "bash -c 'INPUT=$(cat); FP=$(echo \"$INPUT\" | jq -r \".tool_input.file_path // empty\"); if echo \"$FP\" | grep -qE \"\\.entitlements$\"; then echo \"BLOCKED: Do not modify entitlements files without explicit permission.\" >&2; exit 2; fi'"
}
]
}
}
Połączona konfiguracja hooków dla iOS
Poniżej przedstawiono pełny plik .claude/settings.json, którego używam we wszystkich projektach iOS:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"command": "bash -c 'INPUT=$(cat); FP=$(echo \"$INPUT\" | jq -r \".tool_input.file_path // empty\"); if echo \"$FP\" | grep -qE \"\\.(pbxproj|xcworkspace|xib|storyboard|entitlements)$|xcodeproj/|xcworkspace/\"; then echo \"BLOCKED: Do not modify Xcode-managed files. Create Swift files and add manually.\" >&2; exit 2; fi'"
}
],
"PostToolUse": [
{
"matcher": "Edit|Write",
"command": "bash -c 'INPUT=$(cat); FP=$(echo \"$INPUT\" | jq -r \".tool_input.file_path // empty\"); if echo \"$FP\" | grep -qE \"\\.swift$\"; then swiftformat \"$FP\" --quiet 2>/dev/null; fi'"
}
]
}
}
Daje to dwie gwarancje: 1. Agent nie może uszkodzić plików projektu Xcode (blokada PreToolUse) 2. Każdy plik Swift modyfikowany przez agenta jest automatycznie formatowany (formatowanie PostToolUse)
Wzorce architektoniczne dobrze współpracujące z agentami
Nie wszystkie architektury Swift są równie przyjazne dla agentów. Poniższe wzorce dają najlepsze rezultaty, ponieważ są jawne, spójne i dobrze reprezentowane w danych treningowych.
@Observable (nigdy ObservableObject)
Projekty celujące w iOS 26+ powinny korzystać wyłącznie z @Observable. To zarówno nowoczesny wzorzec, jak i wzorzec przyjazny agentom:
// CORRECT — @Observable
@Observable
@MainActor
final class TimerManager {
var timeRemaining: TimeInterval = 0
var state: TimerState = .stopped
func start() {
state = .running
// ...
}
}
// In a view:
struct TimerView: View {
@State private var timer = TimerManager()
var body: some View {
Text(timer.timeRemaining, format: .number)
}
}
// WRONG — ObservableObject (deprecated pattern)
class TimerManager: ObservableObject {
@Published var timeRemaining: TimeInterval = 0
@Published var state: TimerState = .stopped
}
// WRONG — @StateObject (deprecated pattern)
struct TimerView: View {
@StateObject private var timer = TimerManager()
}
Dlaczego @Observable jest przyjazny agentom: Wzorzec jest prostszy (nie wymaga adnotacji @Published), model własności jest czytelniejszy (@State zamiast @StateObject vs. @ObservedObject), a agenty generują z nim mniej błędów, ponieważ zawiera mniej ruchomych elementów.
Warto udokumentować to w CLAUDE.md: Nawet przy iOS 26 jako celu, agenty czasem wracają do wzorców ObservableObject z danych treningowych. Jawny zakaz temu zapobiega.
NavigationStack (nigdy NavigationView)
// CORRECT
NavigationStack {
List(items) { item in
NavigationLink(value: item) {
ItemRow(item: item)
}
}
.navigationDestination(for: Item.self) { item in
ItemDetailView(item: item)
}
}
// WRONG
NavigationView {
List(items) { item in
NavigationLink(destination: ItemDetailView(item: item)) {
ItemRow(item: item)
}
}
}
NavigationStack jest dostępny od iOS 16+ i stanowi jedyny wzorzec nawigacji, którego należy używać w nowym kodzie. Typo-bezpieczny wzorzec navigationDestination(for:) zapobiega tworzeniu niepoprawnych linków nawigacyjnych przez agenta.
SwiftData do utrwalania danych
Modele SwiftData to najczystszy wzorzec utrwalania danych przy wspomaganym przez agentów rozwoju:
@Model
final class GroceryItem {
var name: String
var quantity: Int
var isCompleted: Bool
var category: Category?
var list: GroceryList?
init(name: String, quantity: Int = 1) {
self.name = name
self.quantity = quantity
self.isCompleted = false
}
}
Kluczowe zasady dla agentów pracujących z SwiftData:
1. Klasy z @Model są automatycznie Observable — nie należy dodawać @Observable
2. Należy używać @Bindable do wiązań w formularzach: @Bindable var item: GroceryItem
3. W widokach warto korzystać z @Query dla reaktywnych danych: @Query var items: [GroceryItem]
4. W kodzie poza widokami należy używać modelContext.fetch()
5. Usuwanie relacji wymaga jawnych reguł: .cascade, .nullify, .deny
Współbieżność w Swift 6.2
W nowych projektach warto celować w ścisłą współbieżność Swift 6.2:
// Actor isolation for shared mutable state
@MainActor
@Observable
final class DataManager {
var items: [Item] = []
func loadItems() async throws {
let fetched = try await api.fetchItems()
items = fetched // Safe: @MainActor isolated
}
}
// Sendable conformance for cross-actor transfers
struct Item: Sendable, Identifiable {
let id: UUID
let name: String
let createdAt: Date
}
Wskazówki dla agentów dotyczące współbieżności:
- Wszystkie modele widoków należy oznaczać @MainActor (zapobiega ostrzeżeniom o wyścigach danych)
- Do wszystkich operacji asynchronicznych należy używać async/await (bez completion handlerów)
- Typy wartościowe powinny być Sendable przy transferach między aktorami
- W widokach warto używać Task { } do asynchronicznej inicjalizacji
- nonisolated stosować tylko wtedy, gdy zmierzono potrzebę wydajnościową
System projektowy Liquid Glass (iOS 26+)
iOS 26 wprowadził system projektowy Liquid Glass. Agenty radzą sobie z nim dobrze, gdy otrzymają jawne wskazówki:
// Glass effect on containers
VStack {
// content
}
.glassEffect()
// Glass effect with tint
Button("Action") { }
.glassEffect(.regular.tint(.blue))
// Glass effect on navigation bars (automatic in iOS 26)
NavigationStack {
// content
}
// Navigation bar automatically uses glass material
// Custom glass shapes
RoundedRectangle(cornerRadius: 16)
.fill(.ultraThinMaterial)
.glassEffect()
Warto uwzględnić w CLAUDE.md: „Należy stosować .glassEffect() na tłach sekcji i kontenerach kart. Paski nawigacyjne automatycznie przyjmują materiał szklany w iOS 26. Nie należy ręcznie odtwarzać efektów szkła za pomocą niestandardowych materiałów — wystarczy systemowy modyfikator.”
Kontekst specyficzny dla frameworków
Każdy framework Apple ma aspekty specyficzne dla agentów. Ta sekcja obejmuje frameworki używane w 8 aplikacjach.
HealthKit
Aplikacje, które go używają: Return, Water
HealthKit wymaga starannej obsługi uprawnień i zabezpieczeń platformowych:
// Always check availability and authorization
import HealthKit
@MainActor
@Observable
final class HealthKitManager {
private let store = HKHealthStore()
var isAuthorized = false
func requestAuthorization() async {
guard HKHealthStore.isHealthDataAvailable() else { return }
let types: Set<HKSampleType> = [
HKQuantityType(.dietaryWater),
HKCategoryType(.mindfulSession)
]
do {
try await store.requestAuthorization(toShare: types, read: types)
isAuthorized = true
} catch {
// User denied — do not retry automatically
}
}
}
Zasady dla agentów dotyczące HealthKit:
- Zawsze stosować zabezpieczenie HKHealthStore.isHealthDataAvailable()
- Nigdy nie zakładać autoryzacji — sprawdzać przy każdym zapisie
- Używać #if canImport(HealthKit) w kodzie wieloplatformowym (HealthKit jest niedostępny na tvOS)
- Nigdy nie przechowywać danych zdrowotnych lokalnie poza tym, co zapewnia HealthKit
- W Info.plist należy uwzględnić zarówno NSHealthShareUsageDescription, jak i NSHealthUpdateUsageDescription
SpriteKit
Aplikacje, które go używają: TappyColor, Starfield Destroyer
Model grafu sceny SpriteKit wymaga jawnych wskazówek dla agenta:
## SpriteKit Rules
- Scene hierarchy is a tree of SKNodes with zPosition ordering
- Physics bodies use category bitmasks (UInt32) for collision detection
- Node pooling: pre-allocate reusable nodes (bullets, particles)
- Never add nodes directly to the scene — use layer nodes for organization
- Update loop: `update(_ currentTime:)` runs every frame — keep it fast
- Actions: use SKAction sequences for animations, not manual property updates
- Textures: use texture atlases for performance (.atlas directories)
Mocne strony agentów w SpriteKit: - Tworzenie sekwencji i grup SKAction - Konfigurowanie ciał fizycznych i detekcji kontaktu - Implementowanie maszyn stanów gry - Budowanie nakładek HUD
Słabe strony agentów w SpriteKit: - Pętle gry wrażliwe na wydajność (agent dodaje zbędną pracę na klatkę) - Złożone symulacje fizyczne (własna fizyka przewyższa SKPhysicsBody pod względem precyzji) - Strojenie efektów cząsteczkowych (wizualne, wymaga iteracji)
Metal
Aplikacje, które go używają: amp97, Water, Starfield Destroyer
Metal to framework, z którym agenty radzą sobie najgorzej. Model programowania GPU różni się fundamentalnie od Swift po stronie CPU, a agenty nie są w stanie zweryfikować wyników wizualnych.
## Metal Rules
- Shared types between Swift and Metal go in a bridging header (ShaderTypes.h)
- Triple buffer in-flight frames (semaphore with value 3)
- Test shaders on DEVICE, not simulator (Metal behavior differs)
- Compute shaders: threadgroup size must divide evenly into grid size
- Fragment shaders: output color must be in correct color space (sRGB or linear)
- DO NOT optimize shaders without Instruments GPU profiling data
Co uwzględnić w CLAUDE.md dla projektów Metal: - Definicję struktury Uniforms (współdzieloną między Swift i MSL) - Wzorzec konfiguracji stanu potoku renderowania - Indeksy buforów i ich przeznaczenie - Jakie shadery istnieją i co każdy z nich robi - Znane problemy z precyzją (half vs. float)
Live Activities
Aplikacje, które tego używają: Return
Live Activities wymagają specyficznej konfiguracji, z którą agenty radzą sobie dobrze po udokumentowaniu:
## Live Activities
- ActivityAttributes defined in `TimerActivityAttributes.swift`
- ActivityKit framework: `import ActivityKit`
- Widget extension: `ReturnWidgets/ReturnLiveActivity.swift`
- Start: `Activity<TimerActivityAttributes>.request(attributes:content:)`
- Update: `activity.update(ActivityContent(state:staleDate:))`
- End: `activity.end(ActivityContent(state:staleDate:), dismissalPolicy:)`
- Push token: register for updates via `activity.pushTokenUpdates`
Game Center
Aplikacje, które tego używają: Starfield Destroyer
## Game Center
- Authentication: `GKLocalPlayer.local.authenticateHandler`
- Leaderboards: `GKLeaderboard.submitScore(_:context:player:leaderboardIDs:completionHandler:)`
- Achievements: `GKAchievement.report(_:withCompletionHandler:)` (takes `[GKAchievement]` array)
- Always check `GKLocalPlayer.local.isAuthenticated` before submitting
- Handle authentication failure gracefully (offline play must work)
Wzorce wieloplatformowe
Return obejmuje iOS, watchOS i tvOS. Rozwój wieloplatformowy z agentami wymaga jawnego dokumentowania granic między platformami.
Organizacja współdzielonego kodu
Shared/
├── MeditationSession.swift # Data model (all platforms)
├── SessionStore.swift # iCloud sync (all platforms)
└── SessionHistoryView.swift # UI (adapts per platform)
Return/ # iOS-specific
ReturnWatch Watch App/ # watchOS-specific
ReturnTV/ # tvOS-specific
Zasada dla agentów: „Jeśli plik znajduje się w Shared/, zmiany dotyczą wszystkich platform. Jeśli plik znajduje się w katalogu platformy, zmiany są izolowane. Przed modyfikacją pliku należy zawsze sprawdzić, w którym katalogu się znajduje.”
Strażniki dostępności platformy
// HealthKit: available on iOS and watchOS, not tvOS
#if canImport(HealthKit)
import HealthKit
// HealthKit code here
#endif
// ActivityKit: available on iOS only
#if canImport(ActivityKit)
import ActivityKit
// Live Activity code here
#endif
// WatchKit: available on watchOS only
#if os(watchOS)
import WatchKit
// Watch-specific code here
#endif
Wskazówki dla agenta: „Zawsze należy stosować strażniki #if canImport() lub #if os() podczas korzystania z frameworków specyficznych dla platformy. Nie wolno zakładać, że framework jest dostępny na wszystkich celach kompilacji.”
Adaptacja UI dla poszczególnych platform
struct SessionHistoryView: View {
@Query var sessions: [MeditationSession]
var body: some View {
List(sessions) { session in
SessionRow(session: session)
}
#if os(tvOS)
.focusable()
#endif
#if os(iOS)
.swipeActions {
Button("Delete", role: .destructive) {
// delete
}
}
#endif
}
}
Zaawansowane przepływy pracy
Autonomiczne pętle kompilacja-test-naprawa
Najpotężniejszy wzorzec: przekazanie agentowi specyfikacji funkcji i pozwolenie mu na autonomiczną iterację przez cykle kompilacja-test-naprawa.
Implement a countdown timer that:
1. Starts from a user-selected duration (10, 20, or 30 minutes)
2. Shows remaining time with a circular progress indicator
3. Plays a bell sound on completion
4. Logs the session to HealthKit as mindful minutes
Build after each change. Fix all errors. Run tests when the build succeeds.
Continue until all tests pass and the build is clean.
Agent pisze kod, kompiluje za pomocą MCP, odczytuje ustrukturyzowane błędy, naprawia je i powtarza cykl. Funkcja, która wymagałaby 5–10 ludzkich cykli kompilacja-błąd-naprawa, zostaje ukończona w jednej autonomicznej pętli.
Kiedy to działa: Dobrze zdefiniowane funkcje z jasnymi kryteriami akceptacji.
Kiedy to zawodzi: Otwarte funkcje („niech ładnie wygląda”), kod wrażliwy na wydajność lub cokolwiek wymagające weryfikacji wizualnej.
Delegowanie do subagentów w iOS
System subagentów Claude Code sprawdza się w projektach iOS:
Use a subagent to research the best approach for implementing
iCloud key-value store sync for meditation sessions across iOS,
watchOS, and tvOS. Report back with the recommended pattern.
Subagent eksploruje dokumentację i wzorce kodu w oddzielnym oknie kontekstowym, zwraca podsumowanie, a główna sesja implementuje rekomendację. Dzięki temu badania nie zużywają głównego kontekstu.
Stosowanie wzorców między aplikacjami
Gdy utrzymuje się wiele aplikacji iOS ze spójnymi wzorcami, agenty mogą przenosić wzorce z jednej aplikacji do drugiej:
Look at how Settings.swift works in the Return project
(centralized singleton with validation). Apply the same pattern
to create a Settings.swift for the Water project.
Agent odczytuje wzorzec źródłowy, rozumie strukturę i tworzy spójną implementację w projekcie docelowym.
Podwójna recenzja agentów (Claude + Codex)
W przypadku krytycznych zmian warto użyć dwóch agentów z różnych rodzin modeli:
- Claude Code pisze implementację
- Codex CLI recenzuje ją w oddzielnym przebiegu
# After Claude implements the feature:
codex "Review the changes in the last commit. Focus on Swift 6.2
concurrency correctness, SwiftData relationship integrity,
and potential retain cycles. Report issues only — no praise."
Różne rodziny modeli wychwytują różne klasy błędów. Jest to szczególnie wartościowe w przypadku shaderów Metal i wzorców współbieżności, gdzie łatwo o subtelne błędy.
Co podwójna recenzja wychwytuje, a pojedyncza pomija:
| Typ problemu | Mocna strona Claude | Mocna strona Codex |
|---|---|---|
| Cykle relacji SwiftData | Umiarkowana | Silna (GPT-4o) |
| Luki izolacji @MainActor | Silna | Umiarkowana |
| Wyrównanie buforów Metal | Umiarkowane | Umiarkowane |
| Wykrywanie cykli referencji | Silna (Opus) | Silna (o3) |
| Świadomość deprecjacji API | Silna (nowsze dane treningowe) | Umiarkowana |
| Wyścigi współbieżności | Silna | Silna (wychwytywane inne wzorce) |
Podwójna recenzja nie polega na znajdowaniu większej liczby błędów — chodzi o znajdowanie innych błędów. Każda rodzina modeli ma odmienne tryby awaryjne w rozpoznawaniu wzorców.
Operacje wsadowe na wielu aplikacjach
Gdy zmiana frameworka lub wzorca dotyczy wielu aplikacji:
# Update @Observable pattern across all projects
for project in BananaList Return Water Reps; do
cd ~/Projects/$project
claude -p "Audit all files for any remaining ObservableObject usage.
Convert to @Observable following the pattern in CLAUDE.md.
Build and test after changes." --dangerously-skip-permissions
done
Należy stosować ostrożnie. Flaga --dangerously-skip-permissions jest wymagana w trybie nieinteraktywnym, ale pomija wszystkie kontrole bezpieczeństwa. Należy upewnić się, że hooki PreToolUse chroniące pliki .pbxproj są aktywne.
Studia przypadków z praktyki
Abstrakcyjne porady są łatwe. Poniżej przedstawiono konkretne scenariusze z 8 aplikacji, które ilustrują, jak w praktyce wygląda programowanie iOS wspomagane przez agentów — włącznie z porażkami.
Studium przypadku 1: Dodanie aplikacji TV do Return (sukces)
Zadanie: Dodanie celu tvOS do Return, timera medytacyjnego posiadającego już wersje na iOS i watchOS. Aplikacja TV wymagała nawigacji za pomocą Siri Remote, interfejsu dostosowanego do dużego ekranu oraz synchronizacji ustawień z aplikacją iOS.
Co agent zrobił dobrze:
- Przeczytał istniejący TimerManager na iOS i stworzył TVTimerManager, pomijając Live Activities i HealthKit (niedostępne na tvOS)
- Stworzył niestandardowe style przycisków do nawigacji fokusem Siri Remote (TVCapsuleButtonStyle, TVCircleButtonStyle)
- Zbudował komponent TVStepper, który zastępuje pokrętła wyboru (nieużyteczne z Siri Remote) przyciskami +/-
- Zaimplementował synchronizację ustawień przez App Groups (group.com.941apps.Return)
- Dodał guardy #if os(tvOS) w całym współdzielonym kodzie
- Zbudował i przetestował za pomocą MCP z platform=tvOS Simulator,name=Apple TV
Co musiałem zrobić ręcznie: - Utworzyć cel tvOS w Xcode (File > New > Target > tvOS App) - Dodać nowy cel do projektu Xcode (zmiany w .pbxproj) - Skonfigurować uprawnienie App Groups dla celu TV - Dodać cel TV do istniejącego schematu lub utworzyć nowy - Ręcznie dodać wszystkie pliki Swift stworzone przez agenta do celu TV - Przetestować nawigację Siri Remote osobiście (agent nie jest w stanie ocenić zachowania fokusu)
Rezultat: 15 nowych plików Swift, w pełni funkcjonalna aplikacja TV, zaimplementowana w około 3 godziny pracy wspomaganej przez agenta. Równoważna implementacja ręczna zajęłaby 1–2 dni. Agent obsłużył około 80% kodu, ja zajmowałem się 20%, które wymagało interakcji z interfejsem Xcode i testowania ręcznego.
Studium przypadku 2: Debugowanie shadera Metal w amp97 (częściowa porażka)
Zadanie: Dodanie systemu intensywności opartego na energii do shadera oscyloskopu. Wizualizacja miała pulsować w rytm energii audio.
Co się wydarzyło:
1. Agent napisał poprawną modyfikację shadera Metal, dodając uniform uEnergy i mapowanie tonalne HDR
2. Kod skompilował się bez błędów
3. Na urządzeniu wizualizacja była całkowicie biała — współczynnik intensywności był 10-krotnie za wysoki (3,5 zamiast 0,30)
4. Agent nie mógł zobaczyć białego ekranu, więc nie miał sygnału zwrotnego
5. Zidentyfikowałem problem wizualnie i poprosiłem agenta o zmniejszenie współczynnika
6. Agent go zmniejszył, ale cała maszyna stanów energii była zbyt złożona i psuła wizualizator na inne sposoby
7. Całkowite wycofanie zmian — dwa commity (67959ed i cda4830) wycofane w 869d914
Lekcja: Shadery Metal to najtrudniejsza dziedzina do programowania wspomaganego przez agentów, ponieważ pętla informacji zwrotnej jest przerwana. Agent może zweryfikować składnię (kompiluje się) i semantykę (poprawne typy), ale nie jest w stanie zweryfikować wyniku (wygląda dobrze). Każda modyfikacja shadera zmieniająca zachowanie wizualne wymaga weryfikacji człowieka na urządzeniu.
Co dodałem do CLAUDE.md po tym incydencie: „DO NOT attempt energy state modifications to the oscilloscope shader without extremely careful coefficient testing. Previous attempt broke the visualizer with coefficients 10x too high.”
Studium przypadku 3: Migracja SwiftData w Banana List (sukces)
Zadanie: Migracja modelu danych z V1 do V2, dodanie pola quantity do GroceryItem oraz nowego modelu Category z relacjami.
Co zrobił agent:
1. Przeczytał istniejące definicje modelu V1
2. Stworzył definicje modelu V2 z nowymi polami i relacjami
3. Napisał GroceryMigrationPlan z implementacją protokołu SchemaMigrationPlan
4. Zaimplementował etap migracji V1toV2: dodał domyślne quantity: 1 i category: nil
5. Zaktualizował wszystkie widoki, aby obsługiwały nowe pola
6. Zaktualizował SampleData.swift dla podglądów
7. Zbudował i uruchomił testy za pomocą MCP — wszystkie przeszły
8. Stworzył testy jednostkowe specyficzne dla migracji
Klucz do sukcesu: Agent odniósł sukces, ponieważ migracje SwiftData opierają się na dobrze zdefiniowanym wzorcu protokołu, który jest dokładnie reprezentowany w dokumentacji Apple i danych treningowych. CLAUDE.md jawnie dokumentował model V1, dzięki czemu agent wiedział, z czego migruje.
Studium przypadku 4: Synchronizacja sesji iCloud w Return (sukces ze złożonością)
Zadanie: Implementacja synchronizacji logów sesji medytacyjnych między urządzeniami. Sesje ukończone na Apple TV lub Mac powinny synchronizować się z iPhone’em w celu zapisania w HealthKit.
Co agent wyprodukował:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ tvOS │ │ Mac │ │ Watch │
│ TVTimerMgr │ │ TimerMgr │ │ WatchTimer │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
└───────────────────┼───────────────────┘
│
▼
┌────────────────────────┐
│ SessionStore │
│ (iCloud Key-Value) │
└───────────┬────────────┘
│
▼
┌────────────────────────┐
│ iPhone (on foreground)│
│ → Write to HealthKit │
└────────────────────────┘
Agent:
1. Stworzył model danych MeditationSession z UUID, datami, czasem trwania, urządzeniem źródłowym i statusem synchronizacji z HealthKit
2. Zbudował singleton SessionStore zarządzający NSUbiquitousKeyValueStore do synchronizacji iCloud
3. Zaimplementował rozwiązywanie konfliktów scalania (deduplikacja oparta na UUID)
4. Dodał SessionHistoryView z adaptacjami specyficznymi dla platformy (przesunięcie do usunięcia na iOS, oparte na fokusie na tvOS)
5. Podłączył synchronizację HealthKit po stronie iPhone’a dla sesji z innych urządzeń
Co wymagało iteracji: Początkowa implementacja nie obsługiwała przypadku, gdy aplikacja iPhone uruchamia się w tle (brak powiadomienia o pierwszym planie do synchronizacji). Agent potrzebował konkretnej wskazówki: „Use NSUbiquitousKeyValueStore.didChangeExternallyNotification to trigger sync on background KV changes.” Po tej podpowiedzi implementacja była poprawna.
Lekcja: Agenci dobrze radzą sobie z wieloplatformowymi wzorcami architektonicznymi, gdy architektura jest jasno opisana. Wzorzec synchronizacji iCloud nie jest trywialny, ale opiera się na udokumentowanym wzorcu Apple, który agent zrozumiał. Przypadek brzegowy (synchronizacja w tle) wymagał ludzkiej wiedzy domenowej, ponieważ nie jest dobrze udokumentowany.
Studium przypadku 5: Integracja Game Center w Starfield Destroyer (sukces)
Zadanie: Dodanie tablic wyników i osiągnięć Game Center do strzelanki kosmicznej.
Co agent zrobił dobrze:
- Zaimplementował GKLocalPlayer.local.authenticateHandler w punkcie wejścia aplikacji
- Stworzył GameCenterManager z metodami do przesyłania wyników i raportowania osiągnięć
- Dodał sprawdzanie stanu uwierzytelnienia przed wszystkimi operacjami Game Center
- Obsłużył przypadek offline w elegancki sposób (gra działa bez Game Center, przesyła dane po ponownym połączeniu)
- Stworzył definicje osiągnięć odpowiadające systemowi progresji 8 statków
Co wymagało pracy ręcznej: - Utworzenie tablic wyników i osiągnięć w App Store Connect (portal webowy, niedostępny dla agenta) - Konfiguracja uprawnienia Game Center w Xcode - Testowanie z piaskownicy konta Game Center (wymaga ręcznego logowania na urządzeniu)
Cykl życia projektu z agentami
Rozpoczynanie nowego projektu iOS
Optymalny przepływ pracy przy rozpoczynaniu nowego projektu ze wsparciem agenta:
Faza 1: Konfiguracja przez człowieka (15–30 minut) 1. Utworzenie projektu Xcode (File > New > Project) 2. Konfiguracja podpisywania i możliwości 3. Ustawienie celu wdrożenia i obsługiwanych platform 4. Dodanie wymaganych uprawnień (HealthKit, Game Center itp.) 5. Utworzenie początkowego CLAUDE.md z tożsamością projektu i regułami
Faza 2: Implementacja przez agenta (godziny do dni) 1. Agent tworzy model danych (SwiftData, Core Data lub zwykłe struktury) 2. Agent buduje widoki zgodnie z udokumentowanymi wzorcami 3. Agent implementuje logikę biznesową w klasach menedżerów/serwisów 4. Agent pisze testy jednostkowe 5. Pętla buduj-testuj-naprawiaj za pomocą MCP (autonomicznie)
Faza 3: Integracja przez człowieka (30–60 minut) 1. Dodanie plików stworzonych przez agenta do celów Xcode 2. Weryfikacja podpisywania i uprawnień 3. Testowanie na fizycznym urządzeniu 4. Przegląd układu wizualnego i UX 5. Przesłanie do App Store Connect
Utrzymywanie istniejącego projektu
W przypadku bieżącego rozwoju ustabilizowanych aplikacji:
You: Here's the next feature for Return: add a "Focus Score" that
calculates from session duration and consistency. Show it on
the main timer view. Build and test.
Claude: [reads CLAUDE.md, understands patterns]
[reads TimerManager.swift, Settings.swift]
[creates FocusScore.swift — model with calculation logic]
[creates FocusScoreView.swift — display component]
[integrates into ContentView.swift]
[calls build_sim — 1 error: missing import]
[fixes import]
[calls build_sim — success]
[writes FocusScoreTests.swift]
[calls test_sim — all pass]
Skuteczność agenta rośnie proporcjonalnie do tego, jak dobrze CLAUDE.md odzwierciedla aktualny stan projektu. Warto aktualizować CLAUDE.md po dodaniu istotnych nowych funkcji, zmianie wzorców architektonicznych lub wprowadzeniu nowych frameworków.
Kiedy angażować agenta, a kiedy nie
| Zadanie | Agent? | Dlaczego |
|---|---|---|
| Nowy widok SwiftUI | Tak | Agenci doskonale radzą sobie z deklaratywnym UI |
| Zmiany modelu SwiftData | Tak | Dobrze zdefiniowane, testowalne |
| Testy jednostkowe | Tak | Mechaniczne, oparte na wzorcach |
| Refaktoryzacja | Tak | Systematyczna, wieloplikowa |
| Diagnoza błędów budowania | Tak (przez MCP) | Ustrukturyzowana pętla informacji zwrotnej |
| Nowy cel Xcode | Nie | Wymaga interfejsu Xcode, zmian w .pbxproj |
| Podpisywanie i provisioning | Nie | Oparte na portalu, niedostępne dla agenta |
| Szlif wizualny | Nie | Wymaga ludzkiej oceny estetycznej |
| Strojenie shaderów Metal | Nie | Wymaga testowania GPU na urządzeniu |
| Przesłanie do App Store | Nie | Portal i Xcode Organizer |
| Profilowanie wydajności | Nie | Wymaga Instruments |
| Audyt dostępności | Częściowo | Agent może dodać etykiety, człowiek weryfikuje VoiceOver |
Konfiguracja definicji agentów
Jeśli korzysta się z systemu definicji agentów Claude Code (.claude/agents/), warto utworzyć agenta dedykowanego dla iOS:
---
name: ios-developer
description: iOS development agent with MCP build tools and SwiftUI expertise
tools:
- XcodeBuildMCP
- xcode
---
# iOS Developer Agent
You are an iOS development agent for apps targeting iOS 26+ with SwiftUI.
## Architecture Rules
- @Observable for all view models (NEVER ObservableObject)
- NavigationStack for all navigation (NEVER NavigationView)
- SwiftData for persistence
- Swift 6.2 strict concurrency
- @MainActor on all Observable classes
## Build & Test — Always Use MCP
Prefer MCP tools over raw shell commands for ALL build operations:
- **Build**: `build_sim` / `build_device` (NOT `xcodebuild` via Bash)
- **Test**: `test_sim` / `test_device` (NOT `xcodebuild test` via Bash)
- **Simulators**: `list_sims`, `boot_sim`, `open_sim`
- **Debug**: `debug_attach_sim`, `debug_stack`, `debug_variables`
- **Apple docs**: `DocumentationSearch` (NOT WebSearch for Apple APIs)
- **Swift verification**: `ExecuteSnippet` (NOT `swift` via Bash)
MCP returns structured JSON. Bash returns unstructured text.
## File Management Rules
- NEVER modify .pbxproj, .xcodeproj/, .xcworkspace/, .xib, .storyboard
- Create Swift files in the correct directory
- Report files that need manual addition to Xcode targets
## SwiftData Rules
- @Model classes are automatically Observable — do not add @Observable
- Use @Bindable for form bindings to model properties
- Use @Query in views, modelContext.fetch() elsewhere
- Document relationship delete rules
## When You Get Stuck
- Build errors: use `build_sim` via MCP for structured output
- API questions: use `DocumentationSearch` via Apple MCP
- Swift verification: use `ExecuteSnippet` via Apple MCP
- Never guess — verify with tools
Można odwoływać się do tego agenta za pomocą @ios-developer w sesjach Claude Code.
Wzorce testowania przy wsparciu agentów iOS
Agenty tworzą doskonałe testy jednostkowe, gdy otrzymają jasne wytyczne. Poniżej przedstawiono wzorce, które dają najlepsze rezultaty.
Organizacja plików testowych
# In CLAUDE.md:
## Test Structure
Tests mirror source structure:
- `ReturnTests/TimerManagerTests.swift` tests `TimerManager.swift`
- `ReturnTests/SettingsTests.swift` tests `Settings.swift`
- `ReturnTests/ConstantsTests.swift` tests `Constants.swift`
Test naming: `test_<what>_<condition>_<expected>`
Example: `test_start_whenStopped_transitionsToRunning`
Formułowanie promptów do testów
Skuteczny prompt testowy:
Write unit tests for TimerManager covering:
1. Initial state is .stopped with timeRemaining == selectedDuration
2. start() transitions state to .running
3. pause() from .running transitions to .paused
4. reset() from any state returns to .stopped with original duration
5. start() from .paused resumes (state becomes .running)
6. Edge case: reset() when already stopped is a no-op
7. Edge case: pause() when already paused is a no-op
Follow the existing test pattern in SettingsTests.swift.
Use setUp() to create a fresh TimerManager for each test.
Dlaczego to działa: Ponumerowane kryteria akceptacji dają agentowi listę kontrolną. Odwołanie do istniejącego pliku testowego ustanawia wzorzec. Wskazanie użycia setUp() zapobiega tworzeniu splątanego stanu testów.
Nieskuteczny prompt testowy:
Write tests for TimerManager.
Takie podejście generuje ogólne, powierzchowne testy, które pomijają przypadki brzegowe i mogą nie być zgodne ze wzorcami projektu.
Wzorce testów asynchronicznych
Testowanie kodu opartego na timerach i operacjach asynchronicznych:
// Agent produces this pattern when guided correctly:
final class TimerManagerTests: XCTestCase {
var sut: TimerManager!
@MainActor
override func setUp() {
super.setUp()
sut = TimerManager()
}
@MainActor
func test_start_whenStopped_transitionsToRunning() {
// Given
XCTAssertEqual(sut.state, .stopped)
// When
sut.start()
// Then
XCTAssertEqual(sut.state, .running)
}
@MainActor
func test_timerCountsDown_afterOneSecond() async throws {
// Given
sut.selectedDuration = 10
sut.reset()
sut.start()
// When
try await Task.sleep(for: .seconds(1.1))
// Then
XCTAssertLessThanOrEqual(sut.timeRemaining, 9.0)
}
}
Kluczowe wzorce, o których agenty potrzebują przypomnienia:
- @MainActor w metodach testowych testujących klasy oznaczone @MainActor
- async throws w testach korzystających z Task.sleep lub operacji asynchronicznych
- Tolerancja w asercjach czasowych (1,1 sekundy, nie dokładnie 1,0)
- Czyste setUp() / tearDown() dla izolacji testów
Testowanie migawkowe
W celu wykrywania regresji wizualnych warto rozważyć dodanie swift-snapshot-testing:
Add snapshot tests for the main timer view in three states:
1. Stopped (showing full duration)
2. Running (showing countdown)
3. Completed (showing 00:00 with completion state)
Use SnapshotTesting library. Create reference images on first run.
Agenty poprawnie konfigurują testy migawkowe, ale nie mogą przeglądać obrazów referencyjnych. Początkowe migawki weryfikuje się ręcznie, a następnie testy agenta wychwytują regresje wizualne przy kolejnych zmianach.
Zarządzanie oknem kontekstu w projektach iOS
Okno kontekstu o pojemności 1M tokenów (Opus 4.6) jest duże, ale nie nieskończone. Projekty iOS mają specyficzne aspekty związane z zarządzaniem kontekstem.
Koszt tokenowy plików iOS
| Typ pliku | Typowy rozmiar | Przybliżona liczba tokenów |
|---|---|---|
| Widok SwiftUI (prosty) | 50–100 linii | 500–1 000 |
| Widok SwiftUI (złożony) | 200–400 linii | 2 000–4 000 |
| Model SwiftData | 30–80 linii | 300–800 |
| Klasa menedżera/serwisu | 100–300 linii | 1 000–3 000 |
| Shader Metal (.metal) | 50–200 linii | 500–2 000 |
| Plik testów jednostkowych | 50–200 linii | 500–2 000 |
| CLAUDE.md | 100–300 linii | 1 000–3 000 |
| Odpowiedź MCP (build) | zmienny | 200–2 000 |
| Odpowiedź MCP (testy) | zmienny | 500–5 000 |
Projekt z 50 plikami: Odczytanie wszystkich plików zużywa około 50 000–100 000 tokenów — z łatwością mieści się w oknie 1M. Agent może przechowywać cały projekt w kontekście.
Projekt ze 100+ plikami: Konieczne staje się selektywne czytanie. Agent najpierw odczytuje CLAUDE.md (dzięki adnotacjom struktury plików), a następnie sięga po konkretne pliki w miarę potrzeb. Właśnie dlatego adnotacje plików w CLAUDE.md są tak istotne — kierują agenta do właściwych plików bez konieczności czytania wszystkiego.
Strategie dla dużych projektów
- Szczegółowe adnotacje plików w CLAUDE.md — Agent odczytuje mapę plików i przechodzi bezpośrednio do odpowiednich plików
- Delegowanie do subagentów — Eksplorację i badania można przekierowywać do subagentów (czysty kontekst, zwracają podsumowania)
- Precyzyjne prompty — „Zmodyfikuj SettingsView.swift, dodając nowy przełącznik” jest lepsze niż „zaktualizuj ustawienia”
- Granice sesji — Dla niepowiązanych funkcji lepiej rozpocząć nowe sesje niż wydłużać długą sesję
- Użycie
/compact— Polecenie kompakcji Claude Code podsumowuje konwersację i zwalnia kontekst
Efektywność tokenowa MCP
Jeden z najsilniejszych argumentów za MCP: ustrukturyzowane odpowiedzi JSON zużywają znacznie mniej tokenów niż surowe wyjście xcodebuild.
| Scenariusz | Tokeny (surowy Bash) | Tokeny (MCP) | Oszczędność |
|---|---|---|---|
| Udany build | 3 000–10 000 | 200–500 | 85–95% |
| Nieudany build (1 błąd) | 3 000–10 000 | 300–800 | 90–92% |
| Wyniki testów (20 testów) | 2 000–5 000 | 500–1 000 | 75–80% |
| Lista symulatorów | 500–2 000 | 200–400 | 60–80% |
W typowej sesji deweloperskiej z 10–20 cyklami budowania MCP oszczędza 30 000–150 000 tokenów w porównaniu z surowym xcodebuild — tokenów, które pozostają dostępne na faktyczne rozumowanie kodu.
Rozwiązywanie problemów
„build_sim failed — scheme not found”
Agent próbuje odgadnąć nazwę schematu. Rozwiązanie:
Use discover_projs and list_schemes to find the correct scheme name
for this project before building.
Można też jawnie dodać nazwę schematu do CLAUDE.md:
## Kompilacja
Główny schemat: `Return` (iOS)
Schemat Watch: `ReturnWatch` (watchOS)
Schemat TV: `ReturnTV` (tvOS)
„xcrun mcpbridge — polecenie nie zostało znalezione”
Wymagany jest Xcode 26.3 lub nowszy. Można to sprawdzić poleceniem xcodebuild -version. Jeśli Xcode 26.3+ jest zainstalowany, ale polecenie nadal nie działa:
# Ensure Xcode command line tools are selected
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
# Verify
xcrun mcpbridge --help
„Narzędzia MCP nie pojawiają się w Claude Code”
Narzędzia MCP zarejestrowane w trakcie sesji mogą nie być widoczne do momentu ponownego uruchomienia. Należy zamknąć Claude Code i rozpocząć nową sesję:
# Exit current session (Ctrl+C or /exit)
# Start fresh
claude
Następnie można zweryfikować:
You: List all available MCP tools from XcodeBuildMCP.
„Agent używa xcodebuild przez Bash zamiast MCP”
Agent nie wykrywa narzędzi MCP poprzez Tool Search. Dwa rozwiązania:
- Dodanie jawnych wytycznych do CLAUDE.md (zob. Uczenie agenta korzystania z MCP)
- Bezpośrednie polecenie: „Użyj narzędzia build_sim MCP, a nie xcodebuild przez Bash”
„Kompilacja się udaje, ale agent zgłasza błąd”
XcodeBuildMCP parsuje dane wyjściowe xcodebuild. Jeśli kompilacja generuje ostrzeżenia wyglądające jak błędy (częste przy ostrzeżeniach o przestarzałych elementach), agent może błędnie zinterpretować wynik. Należy sprawdzić rzeczywiste pole statusu w odpowiedzi MCP.
„Symulator zawiesza się podczas uruchamiania”
Należy zamknąć wszystkie symulatory i uruchomić ponownie:
xcrun simctl shutdown all
xcrun simctl boot "iPhone 16 Pro"
Można też poprosić agenta:
Shut down all simulators, then boot a fresh iPhone 16 Pro.
„Agent próbował zmodyfikować .pbxproj mimo reguł w CLAUDE.md”
Reguły w CLAUDE.md to sugestie. Hooki to wymuszanie. Bez hooka PreToolUse blokującego zapisy do .pbxproj agent prędzej czy później podejmie taką próbę. Instalacja hooka:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"command": "bash -c 'INPUT=$(cat); FP=$(echo \"$INPUT\" | jq -r \".tool_input.file_path // empty\"); if echo \"$FP\" | grep -qE \"\\.(pbxproj|xcworkspace|xib|storyboard)$|xcodeproj/|xcworkspace/\"; then echo \"BLOCKED: Do not modify Xcode project files.\" >&2; exit 2; fi'"
}
]
}
}
Reguły mówią „proszę tego nie robić”. Hooki mówią „nie możesz”.
Najczęściej zadawane pytania
Od którego środowiska agentowego zacząć?
Claude Code CLI z XcodeBuildMCP. Oferuje najgłębszą integrację z MCP, najbardziej dojrzały system hooków oraz okno kontekstu 1M (Opus 4.6), które mieści całe projekty iOS w pamięci roboczej. Warto zacząć od tego rozwiązania, a następnie dodać Codex do przeglądów kodu i natywnych agentów Xcode do szybkich edycji inline w miarę rozwoju przepływu pracy.
Czy potrzebuję obu serwerów MCP?
Dla większości programistów sam XcodeBuildMCP pokrywa 90% potrzeb (kompilacja, testy, symulatory, debugowanie). Apple Xcode MCP warto dodać, jeśli potrzebne jest przeszukiwanie dokumentacji, weryfikacja w Swift REPL lub renderowanie podglądów SwiftUI. Zawsze można go dodać później — oba serwery są niezależne.
Czy agenty potrafią utworzyć nowy projekt Xcode od zera?
XcodeBuildMCP zawiera narzędzie create_project, które tworzy szkielet nowych projektów Xcode. Niemniej jednak w przypadku aplikacji produkcyjnych zaleca się utworzenie projektu w Xcode (aby poprawnie skonfigurować podpisywanie, uprawnienia i konfigurację celów), a następnie wykorzystanie agentów do całej implementacji kodu. Pięć minut spędzonych w kreatorze nowego projektu Xcode oszczędza godziny problemów z konfiguracją projektu generowaną przez agenta.
Jak agenty radzą sobie z zależnościami Swift Package Manager?
Dobrze. Package.swift to standardowy plik Swift, który agenty mogą niezawodnie odczytywać i edytować. Dodawanie zależności, aktualizacja zakresów wersji i konfiguracja celów działają poprawnie. Ograniczeniem jest zarządzanie zależnościami oparte na .xcodeproj (interfejs rozwiązywania pakietów w Xcode) — jest ono zarządzane przez Xcode i nie powinno być edytowane przez agenta.
Czy agenty mogą wysyłać aplikacje do App Store?
Nie. Wysyłanie do App Store wymaga użycia Organizera w Xcode, profili provisioningowych, zrzutów ekranu, metadanych i portalu App Store Connect. Żadne z tych narzędzi nie jest dostępne przez MCP ani narzędzia wiersza poleceń w sposób umożliwiający efektywną pracę agentów. Agenty obsługują wszystko aż do archiwizacji — implementację, testowanie, naprawianie błędów i dokumentację. Ostatni etap wysyłania pozostaje w rękach człowieka.
Agenty mogą jednak pomóc z metadanymi App Store. Można poprosić agenta o napisanie opisu aplikacji, słów kluczowych i tekstu „co nowego” na podstawie ostatnich zmian. To zadanie z zakresu generowania tekstu, w którym agenty wyróżniają się.
Jak zarządzać sekretami i kluczami API w programowaniu iOS wspomaganym przez agenta?
Nigdy nie należy commitować sekretów. W przypadku aplikacji iOS łączących się z backendowymi API:
- Pliki
.xcconfigdo konfiguracji specyficznej dla środowiska - Dodanie plików
.xcconfigdo.gitignore - Odwoływanie się do wartości konfiguracyjnych przez ustawienia kompilacji w
Info.plist - Udokumentowanie wymaganych sekretów w CLAUDE.md bez podawania rzeczywistych wartości
## Configuration
API base URL and keys are in `Config.xcconfig` (not committed).
Required keys:
- `API_BASE_URL` — Backend server URL
- `API_KEY` — Authentication token
Create `Config.xcconfig` from `Config.xcconfig.template`.
Agent wie, że klucze istnieją i gdzie są używane, ale nigdy nie widzi rzeczywistych wartości.
A co z animacjami SwiftUI — czy agenty potrafią je pisać?
Agenty piszą kod animacji poprawnie pod względem składniowym, ale nie mogą zweryfikować wyniku wizualnie. Proste animacje (.animation(.spring()), .transition(.slide), withAnimation { }) dają prawidłowe rezultaty. Złożone, wieloetapowe animacje z precyzyjnym timingiem wymagają wizualnej iteracji, której agenty nie są w stanie przeprowadzić.
Skuteczne: „Dodaj animację sprężynową przy przejściu timera między stanami.”
Nieskuteczne: „Spraw, żeby animacja timera była satysfakcjonująca.” (Subiektywne, wymaga dostrojenia wizualnego.)
Jak agenty radzą sobie ze wzorcami obsługi błędów?
Bardzo dobrze. Agenty rozumieją wzorce do/catch, Result i async throws w Swift:
Implement error handling for the HealthKit authorization flow:
1. Check HKHealthStore.isHealthDataAvailable() — show alert if not
2. Request authorization — handle denial gracefully
3. On write failure — retry once, then show error
4. All errors should be user-facing with localized descriptions
Agenty tworzą ustrukturyzowaną obsługę błędów z odpowiednimi komunikatami dla użytkownika. Czasami nadmiernie obsługują błędy (przechwytując wyjątki, które powinny się propagować), dlatego warto przejrzeć bloki catch.
Czy mogę wykorzystać agenty do implementacji dostępności?
Częściowo. Agenty poprawnie dodają etykiety dostępności, podpowiedzi i cechy:
Add accessibility labels to all interactive elements in TimerView:
- Timer display: current time remaining
- Start/Pause button: current state and action
- Reset button: "Reset timer"
- Duration picker: selected duration
Czego agenty nie potrafią: zweryfikować poprawności kolejności nawigacji VoiceOver, przetestować skalowania Dynamic Type ani ocenić współczynników kontrastu kolorów. Do weryfikacji należy użyć Accessibility Inspectora w Xcode.
Jak agenty radzą sobie z migracją Core Data (jeśli nie używa się SwiftData)?
Agenty piszą mapowania migracji Core Data i wersje modeli, ale ręczne kroki w Xcode (tworzenie nowych wersji modeli, wybór aktualnej wersji) nie mogą być zautomatyzowane. Jeśli projekt nadal korzysta z Core Data zamiast SwiftData, należy udokumentować historię wersji modelu w CLAUDE.md:
## Wersje modelu danych Core Data
- V1: Początkowa wersja (GroceryList, GroceryItem)
- V2: Dodano model Category (aktualna)
- Migracja: Lekka, automatyczna dla V1→V2
Jak agenci obsługują podglądy SwiftUI?
Na dwa sposoby:
1. Narzędzie RenderPreview w Apple Xcode MCP renderuje podglądy bez interfejsu graficznego i zwraca wynik. Agent może zweryfikować, czy podgląd się kompiluje i renderuje bez błędów, ale nie jest w stanie ocenić poprawności wizualnej.
2. Weryfikacja oparta na kompilacji za pomocą build_sim potwierdza, że dostawcy podglądów się kompilują. Jeśli podgląd ulegnie awarii w czasie wykonywania, kompilacja nadal kończy się sukcesem — awaria ujawnia się dopiero, gdy Xcode próbuje wyrenderować podgląd.
Do wizualnej weryfikacji podglądów nadal potrzebny jest otwarty Xcode.
A co z visionOS i Apple Vision Pro?
Te same wzorce mają zastosowanie. XcodeBuildMCP obsługuje symulatory visionOS, a wzorce architektoniczne (@Observable, NavigationStack, SwiftData) są identyczne. Kod specyficzny dla RealityKit (treści 3D, przestrzenie immersyjne, śledzenie dłoni) podlega tym samym ograniczeniom co Metal — agenci potrafią napisać poprawny kod, ale nie są w stanie zweryfikować wyniku przestrzennego.
Jak duży może być projekt, zanim agenci zaczną mieć trudności?
Czynnikiem ograniczającym jest rozmiar okna kontekstu. Przy oknie 1M tokenów w Opus 4.6, Claude Code może jednocześnie utrzymywać w aktywnej pamięci roboczej około 50–70 plików Swift. W przypadku większych projektów agent wykorzystuje wyszukiwanie plików i selektywne odczytywanie, aby pracować z podzbiorami bazy kodu. Projekty ze 100+ plikami działają bez problemów — agent po prostu odczytuje pliki na żądanie, zamiast trzymać wszystko w kontekście.
Praktycznym ograniczeniem nie jest liczba plików, lecz spójność bazy kodu. Dobrze udokumentowany projekt z 200 plikami i szczegółowym CLAUDE.md daje lepsze wyniki niż nieudokumentowany projekt z 30 plikami.
Czy muszę znać Swift, żeby używać agentów do tworzenia aplikacji iOS?
Trzeba być w stanie przeglądać wyniki agenta i podejmować decyzje architektoniczne. Nie trzeba pisać każdej linii samodzielnie, ale należy rozumieć Swift na tyle dobrze, aby wychwycić błędne wybory agenta — szczególnie w zakresie współbieżności, zarządzania pamięcią i wzorców specyficznych dla frameworków. Agent jest 10-krotnym wzmacniaczem istniejących umiejętności, a nie ich zamiennikiem.
Jak agenci radzą sobie z konfliktami scalania w plikach Swift?
Agenci niezawodnie rozwiązują konflikty scalania w plikach źródłowych Swift. Standardowe znaczniki konfliktu (<<<<<<<, =======, >>>>>>>) są dobrze rozumiane przez wszystkie środowiska uruchomieniowe agentów. Niemniej konflikty scalania w plikach .pbxproj pozostają zadaniem do ręcznego rozwiązania — nie należy prosić agentów o rozwiązywanie konfliktów w plikach .pbxproj.
Jaki jest koszt uruchamiania agentów do tworzenia aplikacji iOS?
W ramach planu Max Anthropic (Opus 4.6, kontekst 1M) typowa sesja tworzenia aplikacji iOS trwa 30–120 minut i przetwarza 200K–800K tokenów. Wywołania narzędzi MCP generują minimalny narzut (ustrukturyzowane odpowiedzi JSON są bardziej efektywne tokenowo w porównaniu z surowymi wynikami kompilacji). Koszt jest porównywalny z uruchamianiem Claude Code dla dowolnej innej bazy kodu — tworzenie aplikacji iOS nie jest istotnie droższe ani tańsze niż tworzenie aplikacji webowych.
Czy mogę używać agentów z projektami UIKit?
Tak, ale agenci są bardziej efektywni z SwiftUI. UIKit wymaga więcej kodu szablonowego, ma mniej deklaratywną strukturę i często korzysta z plików Interface Builder, których agenci nie mogą edytować. W przypadku projektu UIKit warto rozważyć wykorzystanie agentów do warstwy modelu i logiki biznesowej przy jednoczesnym ręcznym tworzeniu interfejsu, lub stopniową migrację widoków do SwiftUI.
Jak agenci obsługują lokalizację?
Agenci skutecznie tworzą i edytują pliki .xcstrings (katalogi ciągów Xcode). Potrafią dodawać nowe klucze lokalizacyjne, dostarczać tłumaczenia i utrzymywać spójność między językami. Ustrukturyzowany format JSON plików .xcstrings jest przyjazny dla agentów. W przypadku plików .strings (format starszego typu) agenci również radzą sobie dobrze — format klucz-wartość jest prosty.
Częste błędy agentów w iOS (i jak im zapobiegać)
Oto powtarzające się błędy, które zaobserwowałem w tysiącach interakcji z agentami w 8 projektach iOS. Każdy z nich ma strategię zapobiegawczą.
Błąd 1: Mieszanie wzorców Observable
Co się dzieje: Agent używa @Observable w jednym pliku, a ObservableObject w innym, lub dodaje @Observable do klasy @Model (która już jest Observable).
Zapobieganie: Jawne reguły w CLAUDE.md:
- NEVER use ObservableObject — use @Observable
- NEVER add @Observable to @Model classes (already Observable)
- NEVER use @StateObject — use @State with @Observable
- NEVER use @ObservedObject — access @Observable properties directly
Błąd 2: Tworzenie cykli referencji w domknięciach
Co się dzieje: Agent tworzy domknięcia, które silnie przechwytują self, szczególnie w Timer.publish, NotificationCenter i handlerach zakończenia.
Zapobieganie: Wzorzec domknięć w CLAUDE.md:
## Closure Pattern
- Timer callbacks: use `[weak self]` and guard
- NotificationCenter observers: store in `Set<AnyCancellable>` and use `[weak self]`
- Completion handlers: use `[weak self]` for any closure stored beyond the call site
Błąd 3: Ignorowanie wymagań @MainActor
Co się dzieje: Agent tworzy klasy @Observable bez izolacji @MainActor, co powoduje ostrzeżenia współbieżności w Swift 6.2 lub awarie w czasie wykonywania, gdy aktualizacje UI zachodzą poza głównym wątkiem.
Zapobieganie:
## Concurrency Rule
ALL @Observable classes MUST be @MainActor:
```swift
@Observable
@MainActor
final class SomeManager { }
### Błąd 4: Używanie NavigationLink z domknięciem Destination
**Co się dzieje:** Agent używa przestarzałego `NavigationLink(destination:label:)` zamiast bezpiecznego typowo wzorca `NavigationLink(value:)` + `.navigationDestination(for:)`.
**Zapobieganie:**
```markdown
## Navigation Pattern
ALWAYS use value-based navigation:
```swift
NavigationLink(value: item) { ItemRow(item: item) }
.navigationDestination(for: Item.self) { ItemDetailView(item: $0) }
NEVER use: NavigationLink(destination: ItemDetailView(item: item)) { }
### Błąd 5: Sztywne kodowanie nazw symulatorów
**Co się dzieje:** Agent pisze polecenia kompilacji z konkretnymi nazwami symulatorów („iPhone 16 Pro"), które mogą nie istnieć w danym systemie.
**Zapobieganie:** MCP rozwiązuje ten problem — `list_sims` odkrywa dostępne symulatory. W CLAUDE.md:
```markdown
## Simulators
Do NOT hardcode simulator names. Use `list_sims` MCP tool to discover
available devices, then `boot_sim` with the discovered device ID.
Błąd 6: Tworzenie plików w niewłaściwych katalogach
Co się dzieje: Agent tworzy nowy plik widoku w katalogu głównym projektu zamiast w podkatalogu Views/, lub umieszcza model w niewłaściwej grupie.
Zapobieganie: Adnotacje struktury plików w CLAUDE.md wskazują właściwe miejsce. Dodatkowo:
## File Placement Rules
- Views → `AppName/Views/`
- Models → `AppName/Models/`
- Managers → `AppName/Managers/`
- Extensions → `AppName/Extensions/`
- Tests → `AppNameTests/`
Błąd 7: Brak obsługi dostępności platformowej
Co się dzieje: Agent używa HealthKit we współdzielonym kodzie kompilowanym dla tvOS (gdzie HealthKit jest niedostępny) lub używa ActivityKit w kodzie dla watchOS.
Zapobieganie:
## Platform Guards
- HealthKit: `#if canImport(HealthKit)` (unavailable on tvOS)
- ActivityKit: `#if canImport(ActivityKit)` (iOS only)
- WatchKit: `#if os(watchOS)`
- UIKit haptics: `#if os(iOS)` (unavailable on tvOS, watchOS uses WKHaptic)
Błąd 8: Nadmierne komplikowanie prostych funkcji
Co się dzieje: Agent tworzy protokół, rozszerzenie protokołu, konkretną implementację, fabrykę i kontener wstrzykiwania zależności dla czegoś, co powinno być 20-liniową funkcją pomocniczą.
Zapobieganie: Zasada prostoty:
## Architecture Principle
Prefer the simplest solution that handles the requirements.
- Direct implementation over protocol abstraction (unless you have 2+ conforming types)
- Concrete types over generics (unless reuse is proven)
- Extensions on existing types over new wrapper types
Uczciwa ocena
Po wydaniu 8 aplikacji iOS z pomocą agentów AI, oto podsumowanie:
Co agenci zmienili: Szybkość implementacji. To, co zajmowało dni, teraz zajmuje godziny. Widoki SwiftUI, modele SwiftData, testy jednostkowe, refaktoryzacja — wszystko to jest teraz głównie tworzone przez agentów i przeglądane przez człowieka.
Czego agenci nie zmienili: Decyzji architektonicznych, projektowania wizualnego, optymalizacji wydajności ani procesu publikacji w App Store. To nadal pozostaje w gestii człowieka.
Mnożnik jest realny, ale ograniczony. Szacuję 3–5-krotny wzrost produktywności dla dobrze udokumentowanych projektów z odpowiednią konfiguracją MCP i hooków. Nieudokumentowane projekty bez hooków dają może 1,5–2-krotną poprawę — agent poświęca zbyt dużo czasu na domysły zamiast na budowanie.
Inwestycja, która się zwraca: Czas poświęcony na CLAUDE.md, hooki i konfigurację MCP. Każda godzina konfiguracji oszczędza wiele godzin poprawiania błędów agenta. Konfiguracja jest produktem — agent jest silnikiem wykonawczym.
Co mnie zaskoczyło: Jak bardzo serwery MCP zmieniły dynamikę. Przed MCP agenci byli zaawansowanymi edytorami tekstu, które akurat rozumiały Swift. Po MCP są partnerami deweloperskimi, którzy piszą, kompilują, testują, debugują i iterują. Ustrukturyzowana pętla zwrotna to różnica między agentem, który pisze kod, a takim, który dostarcza kod.
Co powiedziałbym sobie z przeszłości: Zacznij od najmniejszej aplikacji (Reps, 14 plików), dopracuj konfigurację MCP i hooków, napisz dokładne CLAUDE.md, a potem skaluj te wzorce na większe projekty. Nie zaczynaj od 63-plikowej aplikacji wieloplatformowej. Inwestycja w infrastrukturę jest taka sama niezależnie od rozmiaru projektu — zrób to raz na małym projekcie, a potem skopiuj do wszystkich pozostałych.
Przyszłość: Natywna integracja agentów w Xcode 26.3 to dopiero początek. Fakt, że Apple dostarcza wsparcie MCP, oznacza, że narzędzia zmierzają w kierunku rozwoju opartego na agentach. Deweloperzy, którzy już teraz inwestują w struktury projektów kompatybilne z agentami — czyste pliki CLAUDE.md, testowalne architektury, zautomatyzowane hooki — będą kumulować zyski z tej inwestycji w miarę doskonalenia narzędzi.
Karta szybkiego dostępu
Instalacja (jednorazowa konfiguracja)
# XcodeBuildMCP (59 tools)
claude mcp add XcodeBuildMCP -s user \
-e XCODEBUILDMCP_SENTRY_DISABLED=true \
-- npx -y xcodebuildmcp@latest mcp
# Apple Xcode MCP (20 tools)
claude mcp add --transport stdio xcode -s user -- xcrun mcpbridge
# Codex MCP setup
codex mcp add xcode -- xcrun mcpbridge
# Verify
claude mcp list
Niezbędne sekcje CLAUDE.md
1. Project identity (bundle ID, target OS, architecture)
2. File structure with annotations
3. Build and test commands
4. Key patterns and rules
5. Prohibitions (NEVER touch .pbxproj)
6. Framework-specific context
Niezbędne hooki
{
"PreToolUse": [{ "matcher": "Edit|Write", "command": "block .pbxproj" }],
"PostToolUse": [{ "matcher": "Edit|Write", "command": "swiftformat" }]
}
Zasady architektury
@Observable (not ObservableObject)
NavigationStack (not NavigationView)
@State (not @StateObject)
SwiftData @Model (not Core Data)
async/await (not completion handlers)
@MainActor (on all Observable classes)
.glassEffect() (Liquid Glass, iOS 26+)
Priorytety narzędzi MCP
Build: build_sim (not xcodebuild via Bash)
Test: test_sim (not xcodebuild test via Bash)
Sim: list_sims/boot_sim (not xcrun simctl via Bash)
Docs: DocumentationSearch (not WebSearch)
REPL: ExecuteSnippet (not swift via Bash)
Dziennik zmian
| Data | Zmiany |
|---|---|
| 2026-04-13 | Pierwsza publikacja. 8 aplikacji, 3 środowiska uruchomieniowe, konfiguracja MCP, wzorce CLAUDE.md, hooki, studia przypadków. |
Przypisy
-
XcodeBuildMCP domyślnie zawiera telemetrię Sentry. Dokumentacja prywatności projektu opisuje, jakie dane są wysyłane: komunikaty o błędach, ślady stosu, a w niektórych przypadkach ścieżki plików. Zmienna środowiskowa
XCODEBUILDMCP_SENTRY_DISABLED=truecałkowicie wyłącza telemetrię. ↩ -
Anthropic, „Model Context Protocol Specification,” modelcontextprotocol.io/specification. Specyfikacja MCP definiuje transport JSON-RPC, odkrywanie narzędzi oraz protokół zasobów, które implementują zarówno XcodeBuildMCP, jak i Apple Xcode MCP. ↩
-
XcodeBuildMCP, github.com/getsentry/XcodeBuildMCP. Projekt open source utrzymywany przez Sentry. 59 narzędzi obejmujących symulator, urządzenia fizyczne, debugowanie i automatyzację UI. Wersjonowanie semantyczne z dziennikiem zmian. ↩
-
Apple wprowadziło serwer Xcode MCP w ramach inicjatywy inteligentnych narzędzi deweloperskich Xcode 26.3, pozycjonując MCP jako warstwę interfejsu między asystentami kodowania AI a zestawem narzędzi Xcode. Oficjalna dokumentacja dostępna w Xcode Release Notes. ↩
-
Rudrank Riyam, „Exploring Xcode Using MCP Tools,” rudrank.com/exploring-xcode-using-mcp-tools-cursor-external-clients, 2026. Niezależne potwierdzenie liczby narzędzi Apple MCP, zależności od XPC oraz możliwości przeszukiwania dokumentacji. ↩
-
Jimenez, C.E., Yang, J., Wettig, A., et al., „SWE-bench: Can Language Models Resolve Real-World GitHub Issues?” ICLR 2024. arxiv.org/abs/2310.06770. Agenci z ustrukturyzowanym dostępem do narzędzi znacząco przewyższali agentów ograniczonych do nieustrukturyzowanych poleceń powłoki. Wyniki te potwierdzają skuteczność ustrukturyzowanych interfejsów MCP dla agentów. ↩
-
Dokumentacja Claude Code CLI, code.claude.com. System hooków, konfiguracja MCP, delegowanie do subagentów oraz definicje agentów. ↩
-
SwiftFormat, github.com/nicklockwood/SwiftFormat. Narzędzie do formatowania kodu Swift używane w hookach PostToolUse w celu zachowania spójnego stylu kodu. ↩
-
Oficjalna strona XcodeBuildMCP, xcodebuildmcp.com. Potwierdza 59 narzędzi MCP na podstawie przykładowego wyjścia CLI. Kategorie narzędzi: symulator, urządzenia fizyczne, debugowanie i automatyzacja UI. Instalacja przez Homebrew lub npx. ↩
-
Swiftjective-C, „Agentic Coding in Xcode 26.3 with Claude Code and Codex,” swiftjectivec.com, luty 2026. Potwierdza, że Xcode 26.3 zawiera natywną obsługę Claude Agent i środowiska uruchomieniowego Codex poprzez Ustawienia > Inteligencja. 20 narzędzi MCP udostępnionych przez
xcrun mcpbridge. ↩ -
Blake Crosley, „Two MCP Servers Made Claude Code an iOS Build System,” blakecrosley.com/blog/xcode-mcp-claude-code, luty 2026. Przewodnik konfiguracji i rzeczywiste wyniki z procesu tworzenia aplikacji iOS tego samego autora. ↩