Swiftui Development

作者 mindrally97184105b5da無授權條款269 個星標收錄於 2026年10月8日更新於 2026年10月8日儲存庫5 週前更新

Guidelines for building SwiftUI applications with MVVM/Clean Architecture, Swift 6 strict concurrency, and modern state management. Use when building SwiftUI views, structuring view models, managing state with @State/@Observable, handling async data flow, or optimizing SwiftUI view performance.

AI 產生的概覽

以 MVVM/Clean Architecture、Swift 6 並行與現代狀態管理建構 SwiftUI 應用程式的指導規範。

功能
此技能提供撰寫 SwiftUI 應用程式碼的參考指引,涵蓋 MVVM 與 Clean Architecture 等架構模式、檢視組合、使用 @State、@Binding、@Observable 與 ObservableObject 的狀態管理、版面配置、動畫、無障礙與測試。它也涵蓋 Swift 6 嚴格並行、記憶體管理與效能最佳化,並附上可觀察檢視模型與可重用檢視修飾器的簡短程式範例。它是純說明文件,不會產生檔案或指令碼。
適用情境
適用於建構或重構 SwiftUI 檢視、組織檢視模型、選擇狀態管理屬性包裝器、處理非同步資料流,或改善 SwiftUI 檢視效能的情境。在以 Swift 6 嚴格並行或 iOS 17+ 現代 API 為目標時同樣適用。
執行需求
不需要任何工具、套件或憑證;它僅為說明文件,不附帶指令碼。其指引假定使用 Swift 6.0+ 與 iOS 17+(並對較低的部署目標提供說明),以及 Xcode 等 Apple 開發環境。

SwiftUI Development

This skill covers best practices for building clear, performant, and maintainable SwiftUI applications, including architecture, state management, Swift 6 concurrency, layout, animation, and testing.

Key Principles

  • Write correct, up-to-date, bug-free, fully functional, secure, and performant code
  • Favor readability, but not at the expense of correctness or safety
  • Fully implement all requested functionality — leave no TODOs, placeholders, or missing pieces
  • Target Swift 6.0+ with strict concurrency checking enabled; treat concurrency warnings as errors
  • Target iOS 17+ where possible to use modern APIs (@Observable, NavigationStack, #Preview); note the minimum deployment target when it forces older patterns

Architecture

  • Use MVVM (Model-View-ViewModel) or Clean Architecture; introduce a Coordinator layer for complex, multi-screen navigation flows
  • Apply SOLID principles to views and view models:
    • Single Responsibility — each view or view model has one reason to change
    • Open/Closed — extend behavior via composition and protocols rather than modifying existing types
    • Liskov Substitution — protocol conformances must be substitutable without surprising callers
    • Interface Segregation — keep protocols small and focused rather than one large "do everything" interface
    • Dependency Inversion — depend on protocol abstractions, not concrete types, and inject dependencies via init
  • Implement protocol-oriented programming; prefer structs over classes for data models
  • Use extensions for code organization and separation of concerns

SwiftUI View Structure

  • Keep views small and focused on a single responsibility
  • Treat 50 lines as a practical ceiling for a body property — past that, extract subviews into small, reusable structs or private extension functions
  • Use @ViewBuilder for custom container views and complex conditional view logic
  • Implement proper view composition patterns

State Management

  • @State — local, value-type view state (Bool, Int, String, small structs)
  • @Binding — two-way data binding with child views
  • @StateObject — use only in the view that creates/owns the object's lifecycle
  • @ObservedObject — use in child views that react to changes but don't own the object
  • @EnvironmentObject / @Environment — use sparingly for broadly shared dependencies or system values; prefer explicit dependency injection via init when a dependency belongs to a specific view hierarchy rather than the whole app
  • @Published — for observable properties on ObservableObject classes (pre-iOS 17 or when ObservableObject is otherwise required)
  • @Observable macro (iOS 17+) — prefer this over ObservableObject/@Published for new view models; it removes the need for @Published on every property and only triggers view updates for properties actually read by that view, which reduces unnecessary redraws

Naming Conventions

  • camelCase for variables, functions, and methods; PascalCase for types (classes, structs, enums, protocols)
  • Use descriptive, verbose names — fetchUserData over getData
  • Prefix boolean variables with is, has, should, etc.
  • Use verb phrases for function names

SwiftUI Best Practices

  • Use SF Symbols for system icons; use semantic colors from the asset catalog for automatic dark mode support
  • Support Dynamic Type and implement proper keyboard avoidance
  • Use NavigationStack (iOS 16+) over the deprecated NavigationView
  • Prefer type-inferred shorthand dot syntax where available (e.g., .background(.blue))
  • Add .contentShape(Rectangle()) to HStack/VStack rows that have transparent backgrounds, so taps register across the whole row rather than only on opaque content

Layout and Styling

  • Use native SwiftUI layout containers (VStack, HStack, ZStack, Grid); use LazyVStack/LazyHStack for dynamic or long lists
  • Use GeometryReader sparingly — it expands to fill all available space and can hurt layout performance; prefer .background(GeometryReader { ... }) scoped to a single view, or the Layout protocol for custom layouts
  • Give list items stable, meaningful ids (from Identifiable) rather than \.self
  • Implement adaptive layouts for different screen sizes
  • Use ViewModifiers for reusable styling; create custom ButtonStyle, TextFieldStyle, etc.

Animations and Transitions

  • Prefer .animation(_:value:) scoped to a specific state value over broad withAnimation calls, especially inside body
  • Reserve withAnimation for animations explicitly triggered by user interaction
  • Implement custom transitions using AnyTransition; use matchedGeometryEffect for hero animations
  • Use TimelineView for high-frequency, time-driven visual updates instead of a Timer + published property

Swift 6 Concurrency & Data Flow

  • Annotate view models with @MainActor; all UI updates must happen on the main actor
  • Prefer .task(id:) over .onAppear for starting async work — it automatically cancels the task when the view disappears or the id changes, avoiding orphaned work
  • Use async/await for asynchronous operations and Result (or typed throws) for error handling
  • Prefer actor types for shared mutable state or services accessed from multiple tasks
  • Mark pure logic functions nonisolated when they don't touch the main actor, to avoid unnecessary hops
  • Never block the main thread — move heavy computation to a detached Task
  • Handle loading, error, and success states explicitly rather than leaving implicit/undefined states

Memory Management & Safety

  • Default to [weak self] in closures that outlive the current scope; use guard let self else { return } at the start of async closures
  • Only use [unowned self] when the closure's lifetime is provably shorter than self's
  • Handle optionals safely — no force unwrapping; use guard for early returns
  • For remote images, use AsyncImage (with a caching layer, or a library like Nuke/Kingfisher for production apps) and apply .resizable() immediately

Performance Optimization

  • Minimize view body recalculations; adopt Equatable conformance where it helps SwiftUI skip redundant diffing
  • Implement proper list diffing with Identifiable items and stable ids
  • Profile with Instruments before optimizing; cache expensive computations rather than recomputing them in body

Accessibility

  • Add accessibility labels, hints, and traits appropriately; support VoiceOver
  • Assign distinct accessibilityIdentifier strings to interactive elements so UI tests can target them reliably
  • Test with accessibility features (Dynamic Type, VoiceOver, Reduce Motion) enabled

Testing and Previews

  • Always provide a preview using #Preview (Xcode 15+) or PreviewProvider on older toolchains, injecting realistic mock data
  • Preview in multiple color schemes and device sizes
  • Structure unit tests with Given-When-Then; generate protocol-based mocks for external dependencies so view models can be tested without hitting real services

Code Quality

  • Write self-documenting code; add comments only for non-obvious logic
  • Follow the Swift API Design Guidelines
  • Use MARK: - Section Name to organize longer files, and place private helpers in a private extension

Common Patterns

View with @Observable ViewModel (iOS 17+)

swift
@Observable@MainActorfinal class ContentViewModel {    var items: [Item] = []    var isLoading = false
    func loadItems() async {        isLoading = true        defer { isLoading = false }        // Load items    }}
struct ContentView: View {    @State private var viewModel = ContentViewModel()
    var body: some View {        List(viewModel.items) { item in            Text(item.name)        }        .task(id: viewModel.items.count) {            await viewModel.loadItems()        }    }}

View with ObservableObject ViewModel (pre-iOS 17 / legacy)

swift
struct ContentView: View {    @StateObject private var viewModel = ContentViewModel()
    var body: some View {        // View implementation    }}
@MainActorclass ContentViewModel: ObservableObject {    @Published var items: [Item] = []    @Published var isLoading = false
    func loadItems() async {        isLoading = true        // Load items        isLoading = false    }}

Reusable View Modifier

swift
struct CardModifier: ViewModifier {    func body(content: Content) -> some View {        content            .padding()            .background(Color(.systemBackground))            .cornerRadius(12)            .shadow(radius: 4)    }}
extension View {    func cardStyle() -> some View {        modifier(CardModifier())    }}

</content>

來源與署名

來源:mindrally/skills位於swiftui-development提交9718410

授權條款: 無授權條款

內容歸原作者所有。SourceWeft 從公開儲存庫中收錄這些內容。

檢舉或申請下架