programming-ios · diff
git:20260509.966244f to git:20260510.fe97ca3
52 added, 55 removed. Audit A to A.
---
name: programming-ios
title: "iOS Development"
- description: "iOS platform patterns, SwiftUI, SwiftData, App Intents, WidgetKit, StoreKit 2, and modern iOS SDK practices. Auto-activates for iPhone and iPad projects."
+ description: "iOS architecture with SwiftUI, SwiftData, App Intents, WidgetKit, and modern platform integrations. Auto-activates for iOS projects."
license: Apache-2.0
- compatibility: "Requires Xcode 16+ and iOS 18+ SDK."
+ compatibility: "Requires Xcode 16+ and iOS 17+ SDK."
capabilities: programming-swift
domains: developer
rules:
- content(ios)
- content(iphone)
- content(ipad)
- content(uikit)
- match(iphone.+app|ios.+app|ipad.+app)
- file(*.xcodeproj)
---
- ## Conventions
+ ## Mental model
- - SwiftUI first — UIKit only for components without SwiftUI equivalent
- - SwiftData for persistence — prefer over Core Data for new projects (iOS 17+)
- - NavigationStack for navigation — NavigationView is deprecated
- - App Intents for Siri, Shortcuts, and Apple Intelligence integration
- - Privacy manifests (PrivacyInfo.xcprivacy) required — declare all API usage reasons
- - Target current and previous major iOS version as minimum deployment target
- - Human Interface Guidelines compliance — platform-native look and feel
+ A modern iOS app is SwiftUI views over `@Observable` models, with SwiftData (or a small repository layer) for persistence and App Intents for system-level integration. UIKit is the escape hatch for what SwiftUI can't yet express. Architectural mistakes show up as massive view bodies, scattered singletons, and tight coupling to `UIApplication` — design for testability by isolating side effects behind protocols.
- ## SwiftUI Patterns
+ ## Architecture
- - NavigationStack with value-based NavigationLink for type-safe programmatic navigation
- - NavigationPath for heterogeneous navigation state management
- - NavigationSplitView for iPad multi-column layouts — collapses to stack on iPhone
- - @Observable model classes — not ObservableObject/@StateObject for new code (iOS 17+)
- - @Bindable for creating bindings to @Observable model properties in views
- - @Environment for dependency injection — custom EnvironmentKey for app services
- - .task modifier for async work tied to view lifecycle — cancels automatically on disappear
- - ViewThatFits and AnyLayout for adaptive layouts across size classes
- - Custom containers with ForEach(subviewOf:) API (iOS 18+)
- - onScrollGeometryChange for tracking scroll position and reacting to scroll state (iOS 18+)
- - MeshGradient for multi-directional color transitions with control point grids (iOS 18+)
+ - Feature-first organization: each feature owns its views, models, intents, and tests in one folder
+ - Domain logic lives in framework-free Swift modules (a separate SPM target) — the UI imports the domain, not the other way around
+ - Side effects (network, persistence, system services) hide behind protocols injected via `@Environment` or initializer parameters
+ - Avoid singletons except for genuinely process-wide resources (logger, telemetry); inject everything else
+ - Keep `App` and `Scene` definitions thin — they wire dependencies and nothing more
- ## Data & Persistence
+ ## SwiftUI patterns
- - SwiftData with @Model macro — automatic schema generation and lightweight migration
- - @Query in SwiftUI views for filtered, sorted, animated data fetching
- - ModelContainer configured at app entry point — inject via .modelContainer modifier
- - CloudKit sync via SwiftData for seamless iCloud persistence
- - @Attribute(.unique) for single-property deduplication, #Unique for compound constraints (iOS 18+)
- - @Relationship for object graphs with cascade/nullify delete rules
- - #Predicate macro for type-safe, compile-checked queries
- - VersionedSchema + SchemaMigrationPlan for non-trivial schema migrations
+ - `@Observable` model classes for view state; `@Bindable` to create bindings to their properties
+ - `NavigationStack` with typed `NavigationLink(value:)` for type-safe routing; `NavigationPath` for heterogeneous stacks
+ - `NavigationSplitView` for iPad/macOS layouts — collapses to stack on iPhone automatically
+ - `.task` modifier for async work tied to view lifetime — cancels on disappear
+ - `.environment(...)` to inject services down the tree; custom `EnvironmentKey` for app-specific dependencies
+ - View bodies should read like a layout description — push computation into the model
- ## App Intents & Intelligence
+ ## Data and persistence
- - AppIntent protocol for actions exposed to Shortcuts, Siri, and Spotlight
- - AppEntity for domain objects discoverable by the system
- - @Parameter with type-safe validation for intent inputs
- - AppShortcutsProvider for suggested shortcuts surfaced proactively
- - @AssistantIntent(schema:) within App Intent Domains for Apple Intelligence integration (iOS 18+)
+ - SwiftData with `@Model` for new projects — schema is derived from the type, lightweight migrations are automatic
+ - `@Query` in views for filtered, sorted, animated fetches
+ - `ModelContainer` configured at the app entry point; injected via `.modelContainer(...)`
+ - CloudKit sync via SwiftData when cross-device persistence is needed
+ - `#Predicate` macro for type-safe queries; `VersionedSchema` + `SchemaMigrationPlan` for non-trivial migrations
+ - For non-SwiftData persistence, hide Core Data / files / keychain behind a repository protocol
- ## WidgetKit & Live Activities
+ ## System integration
- - TimelineProvider with TimelineEntry for widget content scheduling
- - Live Activities via ActivityKit — real-time updates on lock screen and Dynamic Island
- - Dynamic Island presentations: compact, expanded, minimal — design for all three
- - Interactive widgets with AppIntent-backed Button and Toggle (iOS 17+)
- - Push-based widget updates via APNs for server-driven content refresh
+ - App Intents make actions discoverable by Shortcuts, Siri, Spotlight, and Apple Intelligence
+ - `AppEntity` for domain objects the system can reason about; `AppShortcutsProvider` for surfaced shortcuts
+ - Widgets via WidgetKit with `TimelineProvider`; Live Activities via ActivityKit for lock-screen and Dynamic Island
+ - StoreKit 2 (`Product.products(for:)`, `Transaction.currentEntitlements`) — no delegate callbacks, no receipt parsing
+ - `PrivacyInfo.xcprivacy` declares all required-reason API usage — ship with it from day one
- ## StoreKit 2
+ ## UIKit interop
- - Product.products(for:) async API — no delegate callbacks
- - Transaction.currentEntitlements for checking active purchases and subscriptions
- - SubscriptionStoreView and ProductView for system-provided purchase UI
- - StoreKit Testing in Xcode for local purchase simulation without sandbox accounts
- - Transaction.updates AsyncSequence for real-time purchase monitoring
+ - Wrap UIKit views with `UIViewRepresentable` / `UIViewControllerRepresentable` only when SwiftUI lacks an equivalent
+ - Keep the bridge thin: a single representable per feature, not scattered across views
+ - For UIKit-first apps, embed SwiftUI screens via `UIHostingController` — incremental migration works well
+ ## Concurrency
+
+ - Adopt Swift 6 strict concurrency — main-thread mistakes become compile errors
+ - `@MainActor` on view models and anything touching UIKit/SwiftUI
+ - Network and persistence on background actors or detached tasks; results cross back via `await`
+ - Cancel structured tasks (`.task`) automatically; for unstructured work, hold `Task` handles and cancel explicitly
+
## Testing
- - Swift Testing (@Test, #expect, #require) for unit and integration tests
- - @Suite for test grouping, @Test(arguments:) for parameterized tests
- - XCTest for UI automation — XCUIApplication, XCUIElement accessibility queries
- - #Preview macro as living documentation — verify layout across devices and data states
- - Test plans in Xcode for organizing configurations (language, region, arguments)
- - Simulator testing via xcodebuild — target specific device and OS combinations
+ - Swift Testing (`@Test`, `#expect`, `@Suite`) for unit and integration tests
+ - Test the domain target without the app — fast, deterministic, no simulator
+ - `#Preview` doubles as a visual test for layout across states
+ - XCUITest for end-to-end flows; keep them short and focused on critical user paths
+ - Mock system services by injecting the protocol you defined, not by stubbing Apple's classes
+
+ ## Distribution
+
+ - TestFlight for internal and external betas; phased rollouts on App Store releases
+ - Stay current with the Privacy Manifest required-reason API list — Apple expands it regularly
+ - Symbolicate crash reports via dSYMs uploaded with each build