swiftui-developer

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

SwiftUI Developer

SwiftUI开发者

Overview

概述

Expert guidance for building professional SwiftUI applications targeting iOS 17+/macOS 14+ with modern patterns, accessibility compliance, and optimal performance.
为针对iOS 17+/macOS 14+的专业SwiftUI应用程序提供专家指导,涵盖现代开发模式、无障碍合规性和最佳性能优化。

Instructions

操作指南

When writing SwiftUI code, follow this workflow:
编写SwiftUI代码时,请遵循以下工作流程:

1. Assess Requirements

1. 评估需求

  • Target platform (iOS, macOS, visionOS, watchOS)
  • Minimum OS version (determines available APIs)
  • Complexity level (simple view vs. full feature)
  • 目标平台(iOS、macOS、visionOS、watchOS)
  • 最低系统版本(决定可用API范围)
  • 复杂度级别(简单视图 vs 完整功能模块)

2. Choose Architecture

2. 选择架构

For simple views:
  • Use
    @State
    for local state
  • No ViewModel needed for pure display views
For complex features:
  • Use MVVM with
    @Observable
    macro (iOS 17+)
  • Keep ViewModel logic separate from View
  • Use
    @Environment
    for shared data
针对简单视图:
  • 使用
    @State
    管理本地状态
  • 纯展示型视图无需ViewModel
针对复杂功能:
  • 结合
    @Observable
    宏使用MVVM架构(iOS 17+)
  • 保持ViewModel逻辑与View分离
  • 使用
    @Environment
    处理共享数据

3. Apply State Management

3. 应用状态管理

swift
// iOS 17+ Modern Pattern
@Observable
class FeatureViewModel {
    var items: [Item] = []
    @ObservationIgnored var cache: Cache? // Non-observed
}

struct FeatureView: View {
    @State private var viewModel = FeatureViewModel()
    var body: some View { ... }
}
Property Wrapper Selection:
WrapperUse Case
@State
Local value types, simple state, @Observable objects
@Binding
Two-way connection to parent state
@Environment
Shared app-wide data, system values
@Observable
Modern observable objects (iOS 17+)
swift
// iOS 17+ 现代模式
@Observable
class FeatureViewModel {
    var items: [Item] = []
    @ObservationIgnored var cache: Cache? // 不被观察的属性
}

struct FeatureView: View {
    @State private var viewModel = FeatureViewModel()
    var body: some View { ... }
}
属性包装器选择:
包装器使用场景
@State
本地值类型、简单状态、@Observable对象
@Binding
与父组件状态双向绑定
@Environment
应用全局共享数据、系统级值
@Observable
现代可观察对象(iOS 17+)

4. Follow HIG Principles

4. 遵循HIG原则

  • Touch targets: minimum 44×44 points
  • Text: 17pt body minimum, support Dynamic Type
  • Colors: use semantic colors (
    .primary
    ,
    .secondary
    )
  • Accessibility: add
    .accessibilityLabel
    ,
    .accessibilityHint
  • 触摸目标:最小44×44点
  • 文本:正文最小17pt,支持动态类型
  • 颜色:使用语义化颜色(
    .primary
    .secondary
  • 无障碍:添加
    .accessibilityLabel
    .accessibilityHint

5. Optimize Performance

5. 性能优化

  • Extract reusable subviews
  • Use
    LazyVStack
    /
    LazyHStack
    for lists
  • Avoid heavy computation in
    body
  • Keep state minimal and locally scoped
  • 提取可复用子视图
  • 大型列表使用
    LazyVStack
    /
    LazyHStack
  • 避免在
    body
    中执行繁重计算
  • 保持状态最小化并局部作用域

Examples

示例

Example: Settings Screen with Toggle

示例:带开关的设置界面

Input: "Create a settings view with dark mode toggle and notification preferences"
Output:
swift
import SwiftUI

@Observable
class SettingsViewModel {
    var isDarkMode: Bool {
        didSet { UserDefaults.standard.set(isDarkMode, forKey: "darkMode") }
    }
    var notificationsEnabled: Bool {
        didSet { UserDefaults.standard.set(notificationsEnabled, forKey: "notifications") }
    }

    init() {
        isDarkMode = UserDefaults.standard.bool(forKey: "darkMode")
        notificationsEnabled = UserDefaults.standard.bool(forKey: "notifications")
    }
}

struct SettingsView: View {
    @State private var viewModel = SettingsViewModel()

    var body: some View {
        Form {
            Section("Appearance") {
                Toggle("Dark Mode", isOn: $viewModel.isDarkMode)
                    .accessibilityHint("Switches between light and dark appearance")
            }

            Section("Notifications") {
                Toggle("Enable Notifications", isOn: $viewModel.notificationsEnabled)
                    .accessibilityHint("Allows the app to send you notifications")
            }
        }
        .navigationTitle("Settings")
    }
}
输入: "创建包含深色模式开关和通知偏好设置的设置视图"
输出:
swift
import SwiftUI

@Observable
class SettingsViewModel {
    var isDarkMode: Bool {
        didSet { UserDefaults.standard.set(isDarkMode, forKey: "darkMode") }
    }
    var notificationsEnabled: Bool {
        didSet { UserDefaults.standard.set(notificationsEnabled, forKey: "notifications") }
    }

    init() {
        isDarkMode = UserDefaults.standard.bool(forKey: "darkMode")
        notificationsEnabled = UserDefaults.standard.bool(forKey: "notifications")
    }
}

struct SettingsView: View {
    @State private var viewModel = SettingsViewModel()

    var body: some View {
        Form {
            Section("外观") {
                Toggle("深色模式", isOn: $viewModel.isDarkMode)
                    .accessibilityHint("在浅色和深色外观之间切换")
            }

            Section("通知") {
                Toggle("启用通知", isOn: $viewModel.notificationsEnabled)
                    .accessibilityHint("允许应用向您发送通知")
            }
        }
        .navigationTitle("设置")
    }
}

Example: List with Navigation

示例:带导航的列表

Input: "Create a list of items with detail navigation"
Output:
swift
import SwiftUI

struct Item: Identifiable {
    let id = UUID()
    let title: String
    let subtitle: String
}

struct ItemListView: View {
    let items: [Item]

    var body: some View {
        List(items) { item in
            NavigationLink(value: item) {
                VStack(alignment: .leading, spacing: 4) {
                    Text(item.title)
                        .font(.headline)
                    Text(item.subtitle)
                        .font(.subheadline)
                        .foregroundStyle(.secondary)
                }
                .padding(.vertical, 4)
            }
            .accessibilityLabel("\(item.title), \(item.subtitle)")
        }
        .navigationTitle("Items")
        .navigationDestination(for: Item.self) { item in
            ItemDetailView(item: item)
        }
    }
}
输入: "创建带详情页导航的项目列表"
输出:
swift
import SwiftUI

struct Item: Identifiable {
    let id = UUID()
    let title: String
    let subtitle: String
}

struct ItemListView: View {
    let items: [Item]

    var body: some View {
        List(items) { item in
            NavigationLink(value: item) {
                VStack(alignment: .leading, spacing: 4) {
                    Text(item.title)
                        .font(.headline)
                    Text(item.subtitle)
                        .font(.subheadline)
                        .foregroundStyle(.secondary)
                }
                .padding(.vertical, 4)
            }
            .accessibilityLabel("\(item.title), \(item.subtitle)")
        }
        .navigationTitle("项目")
        .navigationDestination(for: Item.self) { item in
            ItemDetailView(item: item)
        }
    }
}

Example: Async Data Loading

示例:异步数据加载

Input: "Create a view that loads data from an API"
Output:
swift
import SwiftUI

@Observable
class DataViewModel {
    var items: [Item] = []
    var isLoading = false
    var errorMessage: String?

    func loadData() async {
        isLoading = true
        errorMessage = nil

        do {
            items = try await APIService.shared.fetchItems()
        } catch {
            errorMessage = error.localizedDescription
        }

        isLoading = false
    }
}

struct DataView: View {
    @State private var viewModel = DataViewModel()

    var body: some View {
        Group {
            if viewModel.isLoading {
                ProgressView("Loading...")
            } else if let error = viewModel.errorMessage {
                ContentUnavailableView(
                    "Error",
                    systemImage: "exclamationmark.triangle",
                    description: Text(error)
                )
            } else {
                List(viewModel.items) { item in
                    Text(item.title)
                }
            }
        }
        .task {
            await viewModel.loadData()
        }
        .refreshable {
            await viewModel.loadData()
        }
    }
}
输入: "创建从API加载数据的视图"
输出:
swift
import SwiftUI

@Observable
class DataViewModel {
    var items: [Item] = []
    var isLoading = false
    var errorMessage: String?

    func loadData() async {
        isLoading = true
        errorMessage = nil

        do {
            items = try await APIService.shared.fetchItems()
        } catch {
            errorMessage = error.localizedDescription
        }

        isLoading = false
    }
}

struct DataView: View {
    @State private var viewModel = DataViewModel()

    var body: some View {
        Group {
            if viewModel.isLoading {
                ProgressView("加载中...")
            } else if let error = viewModel.errorMessage {
                ContentUnavailableView(
                    "加载失败",
                    systemImage: "exclamationmark.triangle",
                    description: Text(error)
                )
            } else {
                List(viewModel.items) { item in
                    Text(item.title)
                }
            }
        }
        .task {
            await viewModel.loadData()
        }
        .refreshable {
            await viewModel.loadData()
        }
    }
}

Guidelines

准则

Do

推荐做法

  • Use
    @Observable
    for iOS 17+ projects (better performance)
  • Support Dynamic Type with
    .font(.body)
    etc.
  • Add accessibility labels to interactive elements
  • Use
    LazyVStack
    /
    LazyHStack
    for large collections
  • Extract complex subviews to prevent unnecessary redraws
  • Use semantic colors for automatic dark mode support
  • iOS 17+项目使用
    @Observable
    (性能更优)
  • 使用
    .font(.body)
    等方式支持动态类型
  • 为交互元素添加无障碍标签
  • 大型集合使用
    LazyVStack
    /
    LazyHStack
  • 提取复杂子视图以避免不必要的重绘
  • 使用语义化颜色自动适配深色模式

Don't

不推荐做法

  • Use
    @State
    with reference types (causes memory leaks)
  • Use
    @ObservedObject
    to create objects in view (use
    @StateObject
    or
    @State
    )
  • Put heavy computation in
    body
    property
  • Hardcode colors/sizes (breaks accessibility)
  • Ignore the 44×44pt minimum touch target
  • Skip accessibility labels on buttons/images
  • 对引用类型使用
    @State
    (会导致内存泄漏)
  • 在视图中创建
    @ObservedObject
    对象(应使用
    @StateObject
    @State
  • body
    属性中执行繁重计算
  • 硬编码颜色/尺寸(破坏无障碍体验)
  • 忽略44×44pt最小触摸目标要求
  • 不为按钮/图片添加无障碍标签

iOS 18+ Features

iOS 18+新特性

  • Floating tab bar with sidebar flexibility
  • .presentationSizing(.form)
    for sheets
  • Zoom navigation transitions
  • Control Center widgets
  • @Entry
    macro for environment keys
  • Mesh gradients
  • 支持侧边栏灵活布局的浮动标签栏
  • 表单样式的
    .presentationSizing(.form)
    弹窗
  • 缩放导航过渡效果
  • 控制中心小组件
  • 用于环境键的
    @Entry
  • 网格渐变

Additional Resources

额外资源

See
reference/
directory for:
  • state-management.md
    - Property wrapper decision guide
  • hig-checklist.md
    - HIG compliance checklist
请查看
reference/
目录下的内容:
  • state-management.md
    - 属性包装器选择指南
  • hig-checklist.md
    - HIG合规性检查清单