swiftui-expert

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

SwiftUI Expert Skill

SwiftUI专家技能

Overview

概述

Use this skill to build, review, or improve SwiftUI features with correct state management, modern API usage, Swift concurrency best practices, optimal view composition, and iOS 26+ Liquid Glass styling. Prioritize native APIs, Apple design guidance, and performance-conscious patterns. This skill focuses on facts and best practices without enforcing specific architectural patterns.
For architectural decisions (MVVM, MVC, VIPER, Clean Architecture, Coordinator, two-layer view patterns), defer to the
architecture-design-skill
.

使用此技能可构建、评审或改进SwiftUI功能,确保正确的状态管理、现代API使用、Swift并发最佳实践、最优视图组合,以及iOS 26+的Liquid Glass样式。优先使用原生API、Apple设计指南和注重性能的模式。本技能专注于事实和最佳实践,不强制特定架构模式。
架构决策(如MVVM、MVC、VIPER、Clean Architecture、Coordinator、双层视图模式)请参考
architecture-design-skill

Workflow Decision Tree

工作流决策树

1) Review existing SwiftUI code

1) 评审现有SwiftUI代码

  • Check property wrapper usage against the selection guide (see
    references/state-management.md
    )
  • Verify modern API usage (see
    references/modern-apis.md
    )
  • Verify view composition follows extraction rules (see
    references/view-composition.md
    )
  • Check performance patterns are applied (see
    references/performance-patterns.md
    )
  • Verify list patterns use stable identity (see
    references/list-patterns.md
    )
  • Check animation patterns for correctness (see
    references/animation-basics.md
    ,
    references/animation-transitions.md
    )
  • Inspect Liquid Glass usage for correctness (see
    references/liquid-glass.md
    )
  • 对照选择指南检查属性包装器的使用(详见
    references/state-management.md
  • 验证现代API的使用(详见
    references/modern-apis.md
  • 验证视图组合是否遵循提取规则(详见
    references/view-composition.md
  • 检查是否应用了性能优化模式(详见
    references/performance-patterns.md
  • 验证列表模式是否使用稳定标识(详见
    references/list-patterns.md
  • 检查动画模式的正确性(详见
    references/animation-basics.md
    references/animation-transitions.md
  • 检查Liquid Glass的使用是否正确(详见
    references/liquid-glass.md

2) Improve existing SwiftUI code

2) 改进现有SwiftUI代码

  • Audit state management for correct wrapper selection (prefer
    @Observable
    over
    ObservableObject
    )
  • Replace deprecated APIs with modern equivalents (see
    references/modern-apis.md
    )
  • Extract complex views into separate subviews (see
    references/view-composition.md
    )
  • Refactor hot paths to minimize redundant state updates (see
    references/performance-patterns.md
    )
  • Ensure ForEach uses stable identity (see
    references/list-patterns.md
    )
  • Improve animation patterns (see
    references/animation-basics.md
    ,
    references/animation-transitions.md
    )
  • Suggest image downsampling when
    UIImage(data:)
    is used (optional, see
    references/image-optimization.md
    )
  • Adopt Liquid Glass only when explicitly requested by the user
  • 审计状态管理,确保包装器选择正确(优先使用
    @Observable
    而非
    ObservableObject
  • 用现代等效API替换已弃用的API(详见
    references/modern-apis.md
  • 将复杂视图提取为独立子视图(详见
    references/view-composition.md
  • 重构热点路径,减少冗余状态更新(详见
    references/performance-patterns.md
  • 确保ForEach使用稳定标识(详见
    references/list-patterns.md
  • 优化动画模式(详见
    references/animation-basics.md
    references/animation-transitions.md
  • 当使用
    UIImage(data:)
    时,建议进行图片下采样(可选,详见
    references/image-optimization.md
  • 仅在用户明确要求时才采用Liquid Glass

3) Implement new SwiftUI feature

3) 实现新的SwiftUI功能

  • Design data flow first: identify owned vs injected state (see
    references/state-management.md
    )
  • Use modern APIs (no deprecated modifiers or patterns, see
    references/modern-apis.md
    )
  • Use
    @Observable
    for shared state (with
    @MainActor
    if not using default actor isolation)
  • Structure views for optimal diffing: extract subviews early, keep views small (see
    references/view-composition.md
    )
  • Separate business logic into testable models when needed (see
    references/state-management.md#when-to-use-a-viewmodel
    )
  • Use correct animation patterns (see
    references/animation-basics.md
    ,
    references/animation-transitions.md
    ,
    references/animation-advanced.md
    )
  • Apply glass effects after layout/appearance modifiers (see
    references/liquid-glass.md
    )
  • Gate iOS 26+ features with
    #available
    and provide fallbacks

  • 先设计数据流:区分自有状态与注入状态(详见
    references/state-management.md
  • 使用现代API(避免已弃用的修饰符或模式,详见
    references/modern-apis.md
  • 对共享状态使用
    @Observable
    (若未使用默认actor隔离,需标记
    @MainActor
  • 构建视图时优化diff性能:尽早提取子视图,保持视图轻量化(详见
    references/view-composition.md
  • 必要时将业务逻辑分离为可测试的模型(详见
    references/state-management.md#when-to-use-a-viewmodel
  • 使用正确的动画模式(详见
    references/animation-basics.md
    references/animation-transitions.md
    references/animation-advanced.md
  • 在布局/外观修饰符之后应用玻璃效果(详见
    references/liquid-glass.md
  • 使用
    #available
    为iOS 26+功能提供降级方案

Core Guidelines

核心准则

State Management

状态管理

  • Always prefer
    @Observable
    over
    ObservableObject
    for new code
  • Mark
    @Observable
    classes with
    @MainActor
    unless using default actor isolation
  • Always mark
    @State
    and
    @StateObject
    as
    private
    (makes dependencies clear)
  • Never declare passed values as
    @State
    or
    @StateObject
    (they only accept initial values)
  • Use
    @State
    with
    @Observable
    classes (not
    @StateObject
    )
  • @Binding
    only when child needs to modify parent state
  • @Bindable
    for injected
    @Observable
    objects needing bindings
  • Use
    let
    for read-only values;
    var
    +
    .onChange()
    for reactive reads
  • Legacy:
    @StateObject
    for owned
    ObservableObject
    ;
    @ObservedObject
    for injected
  • Nested
    ObservableObject
    doesn't work (pass nested objects directly);
    @Observable
    handles nesting fine
  • 新代码始终优先使用
    @Observable
    而非
    ObservableObject
  • @Observable
    类需标记
    @MainActor
    ,除非使用默认actor隔离
  • @State
    @StateObject
    始终标记为
    private
    (明确依赖关系)
  • 绝不要将传入值声明为
    @State
    @StateObject
    (它们仅接受初始值)
  • 结合
    @State
    @Observable
    类使用(而非
    @StateObject
  • 仅当子视图需要修改父视图状态时使用
    @Binding
  • 对于需要绑定的注入式
    @Observable
    对象,使用
    @Bindable
  • 只读值使用
    let
    ;响应式读取使用
    var
    +
    .onChange()
  • 遗留用法:
    @StateObject
    用于自有
    ObservableObject
    @ObservedObject
    用于注入式对象
  • 嵌套
    ObservableObject
    无法正常工作(需直接传递嵌套对象);
    @Observable
    可完美处理嵌套

When to Use a ViewModel

何时使用ViewModel

Use a separate model class (often called a ViewModel) when:
  • Testability: you need to unit-test state transitions or business logic
  • Complex state: multiple interdependent state properties that evolve together
  • Async coordination: orchestrating multiple async operations with loading/error state
  • Reuse across views: the same logic is needed in more than one view
For simple views with straightforward display logic, keeping
@State
directly in the view is fine and often cleaner.
This is a practical guide, not an MVVM mandate — see
architecture-design-skill
if you need to decide on an app-wide architectural pattern.
当满足以下条件时,使用独立的模型类(通常称为ViewModel):
  • 可测试性:需要对状态转换或业务逻辑进行单元测试
  • 复杂状态:存在多个相互依赖、共同演变的状态属性
  • 异步协调:需要协调多个带有加载/错误状态的异步操作
  • 跨视图复用:多个视图需要使用相同的逻辑
对于具有简单展示逻辑的视图,直接在视图中使用
@State
通常更简洁清晰。
这是一份实用指南,而非MVVM强制要求——若需要决定应用级架构模式,请参考
architecture-design-skill

View Composition

视图组合

  • Prefer modifiers over conditional views for state changes (maintains view identity)
  • Extract complex views into separate
    struct
    subviews for performance (not
    @ViewBuilder
    functions)
  • Keep views small; each view should have one clear responsibility
  • Keep view
    body
    simple and pure (no side effects or complex logic)
  • Use
    @ViewBuilder
    functions only for small, simple sections
  • Prefer
    @ViewBuilder let content: Content
    over closure-based content properties in containers
  • Use specialized built-in components when they fit:
    Label
    ,
    GroupBox
    ,
    Form
    ,
    Section
  • Build custom view styles (
    ButtonStyle
    ,
    LabelStyle
    ) to reuse styling across instances
  • Action handlers should reference methods, not contain inline logic
  • Use relative layout over hard-coded constants
  • Views should work in any context (don't assume screen size or presentation style)
  • 优先使用修饰符而非条件视图处理状态变化(保持视图标识稳定)
  • 将复杂视图提取为独立的
    struct
    子视图以提升性能(而非
    @ViewBuilder
    函数)
  • 保持视图轻量化:每个视图应仅有一个明确职责
  • 保持视图
    body
    简洁纯净(无副作用或复杂逻辑)
  • 仅在小型简单场景中使用
    @ViewBuilder
    函数
  • 容器视图优先使用
    @ViewBuilder let content: Content
    而非闭包型内容属性
  • 合适时使用专用原生组件:
    Label
    GroupBox
    Form
    Section
  • 构建自定义视图样式(
    ButtonStyle
    LabelStyle
    )以在多个实例间复用样式
  • 事件处理程序应引用方法,而非包含内联逻辑
  • 使用相对布局而非硬编码常量
  • 视图应适配任意上下文(不要假设屏幕尺寸或展示样式)

Reusability Recommendation

复用性建议

Prefer passing primitive/value types to presentational (content) views rather than full model objects. This makes views more reusable, simplifies previews, and reduces dependencies.
swift
// Preferred for pure display views
struct UserRow: View {
    let name: String
    let avatarURL: URL?
    let isOnline: Bool
}

// Acceptable when the view needs the full model or has bindings to it
struct UserEditor: View {
    @Bindable var user: UserModel
}
This is a recommendation for reusability, not a strict rule. Views that edit or coordinate model state often need the model directly.
对于展示型(内容)视图,优先传递原始值/值类型而非完整模型对象。这会提升视图复用性,简化预览,并减少依赖。
swift
// 纯展示视图的推荐写法
struct UserRow: View {
    let name: String
    let avatarURL: URL?
    let isOnline: Bool
}

// 当视图需要完整模型或其绑定时,此写法也可接受
struct UserEditor: View {
    @Bindable var user: UserModel
}
这是复用性建议,而非严格规则。用于编辑或协调模型状态的视图通常需要直接使用模型。

Modern APIs

现代API

  • Use
    foregroundStyle()
    instead of
    foregroundColor()
  • Use
    clipShape(.rect(cornerRadius:))
    instead of
    cornerRadius()
  • Use
    Tab
    API instead of
    tabItem()
    (iOS 18+)
  • Use
    Button
    instead of
    onTapGesture()
    (unless need location/count)
  • Use
    NavigationStack
    instead of
    NavigationView
  • Use
    navigationDestination(for:)
    for type-safe navigation
  • Use two-parameter or no-parameter
    onChange()
    variant
  • Use
    ImageRenderer
    for rendering SwiftUI views
  • Use
    .sheet(item:)
    instead of
    .sheet(isPresented:)
    for model-based content
  • Sheets should own their actions and call
    dismiss()
    internally
  • Use
    ScrollViewReader
    for programmatic scrolling with stable IDs
  • Avoid
    UIScreen.main.bounds
    for sizing
  • Avoid
    GeometryReader
    when alternatives exist (e.g.,
    containerRelativeFrame()
    )
  • 使用
    foregroundStyle()
    替代
    foregroundColor()
  • 使用
    clipShape(.rect(cornerRadius:))
    替代
    cornerRadius()
  • 使用
    Tab
    API替代
    tabItem()
    (iOS 18+)
  • 使用
    Button
    替代
    onTapGesture()
    (除非需要位置/点击次数)
  • 使用
    NavigationStack
    替代
    NavigationView
  • 使用
    navigationDestination(for:)
    实现类型安全的导航
  • 使用双参数或无参数的
    onChange()
    变体
  • 使用
    ImageRenderer
    渲染SwiftUI视图
  • 使用
    .sheet(item:)
    替代
    .sheet(isPresented:)
    实现基于模型的内容展示
  • Sheet应自行管理操作并在内部调用
    dismiss()
  • 使用
    ScrollViewReader
    结合稳定ID实现程序化滚动
  • 避免使用
    UIScreen.main.bounds
    进行尺寸计算
  • 有替代方案时避免使用
    GeometryReader
    (如
    containerRelativeFrame()

Swift Best Practices

Swift最佳实践

  • Use modern Text formatting (
    .format
    parameters, not
    String(format:)
    )
  • Use
    localizedStandardContains()
    for user-input filtering (not
    contains()
    )
  • Prefer static member lookup (
    .blue
    vs
    Color.blue
    )
  • Use
    .task
    modifier for automatic cancellation of async work
  • Use
    .task(id:)
    for value-dependent tasks
  • 使用现代文本格式化(
    .format
    参数,而非
    String(format:)
  • 对用户输入过滤使用
    localizedStandardContains()
    (而非
    contains()
  • 优先使用静态成员查找(
    .blue
    而非
    Color.blue
  • 使用
    .task
    修饰符自动取消异步任务
  • 使用
    .task(id:)
    处理依赖值的任务

Performance

性能优化

  • Pass only needed values to views (avoid large "config" or "context" objects)
  • Eliminate unnecessary dependencies to reduce update fan-out
  • Check for value changes before assigning state in hot paths
  • Avoid redundant state updates in
    onReceive
    ,
    onChange
    , scroll handlers
  • Minimize work in frequently executed code paths
  • Use
    LazyVStack
    /
    LazyHStack
    for large lists
  • Use stable identity for
    ForEach
    (never
    .indices
    for dynamic content)
  • Ensure constant number of views per
    ForEach
    element
  • Avoid inline filtering in
    ForEach
    (prefilter and cache)
  • Avoid
    AnyView
    in list rows
  • Consider POD views for fast diffing (or wrap expensive views in POD parents)
  • Suggest image downsampling when
    UIImage(data:)
    is encountered (optional optimization)
  • Avoid layout thrash (deep hierarchies, excessive
    GeometryReader
    )
  • Gate frequent geometry updates by thresholds
  • Use
    Self._printChanges()
    to debug unexpected view updates
  • 仅向视图传递所需值(避免大型“配置”或“上下文”对象)
  • 消除不必要的依赖以减少更新扩散
  • 在热点路径中,赋值状态前先检查值是否变化
  • 避免在
    onReceive
    onChange
    、滚动处理程序中进行冗余状态更新
  • 尽量减少频繁执行代码路径中的工作
  • 大型列表使用
    LazyVStack
    /
    LazyHStack
  • ForEach
    使用稳定标识(动态内容绝不要使用
    .indices
  • 确保
    ForEach
    每个元素对应的视图数量恒定
  • 避免在
    ForEach
    中进行内联过滤(提前过滤并缓存)
  • 列表行中避免使用
    AnyView
  • 考虑使用POD视图以加速diff(或将高性能开销视图包裹在POD父视图中)
  • 当遇到
    UIImage(data:)
    时,建议进行图片下采样(可选优化)
  • 避免布局抖动(深层层级、过度使用
    GeometryReader
  • 通过阈值控制频繁的几何更新
  • 使用
    Self._printChanges()
    调试意外的视图更新

Animations

动画

  • Use
    .animation(_:value:)
    with value parameter (deprecated version without value is too broad)
  • Use
    withAnimation
    for event-driven animations (button taps, gestures)
  • Prefer transforms (
    offset
    ,
    scale
    ,
    rotation
    ) over layout changes (
    frame
    ) for performance
  • Transitions require animations outside the conditional structure
  • Custom
    Animatable
    implementations must have explicit
    animatableData
  • Use
    .phaseAnimator
    for multi-step sequences (iOS 17+)
  • Use
    .keyframeAnimator
    for precise timing control (iOS 17+)
  • Animation completion handlers need
    .transaction(value:)
    for reexecution
  • Implicit animations override explicit animations (later in view tree wins)
  • 使用带value参数的
    .animation(_:value:)
    (不带value的已弃用版本范围过广)
  • 事件驱动的动画使用
    withAnimation
    (如按钮点击、手势)
  • 优先使用变换(
    offset
    scale
    rotation
    )而非布局变化(
    frame
    )以提升性能
  • 过渡动画需在条件结构外部设置
  • 自定义
    Animatable
    实现必须包含显式的
    animatableData
  • 多步序列动画使用
    .phaseAnimator
    (iOS 17+)
  • 需要精确时间控制的动画使用
    .keyframeAnimator
    (iOS 17+)
  • 动画完成处理程序需使用
    .transaction(value:)
    以支持重新执行
  • 隐式动画会覆盖显式动画(视图树中靠后的动画优先级更高)

Liquid Glass (iOS 26+)

Liquid Glass(iOS 26+)

Only adopt when explicitly requested by the user.
  • Use native
    glassEffect
    ,
    GlassEffectContainer
    , and glass button styles
  • Wrap multiple glass elements in
    GlassEffectContainer
  • Apply
    .glassEffect()
    after layout and visual modifiers
  • Use
    .interactive()
    only for tappable/focusable elements
  • Use
    glassEffectID
    with
    @Namespace
    for morphing transitions

仅在用户明确要求时才采用。
  • 使用原生
    glassEffect
    GlassEffectContainer
    和玻璃按钮样式
  • 将多个玻璃元素包裹在
    GlassEffectContainer
  • 在布局和视觉修饰符之后应用
    .glassEffect()
  • 仅对可点击/可聚焦元素使用
    .interactive()
  • 使用
    glassEffectID
    结合
    @Namespace
    实现变形过渡

Quick Reference

快速参考

Property Wrapper Selection (Modern)

属性包装器选择(现代)

WrapperUse When
@State
Internal view state (must be
private
), or owned
@Observable
class
@Binding
Child modifies parent's state
@Bindable
Injected
@Observable
needing bindings
let
Read-only value from parent
var
Read-only value watched via
.onChange()
Legacy (Pre-iOS 17):
WrapperUse When
@StateObject
View owns an
ObservableObject
(use
@State
with
@Observable
instead)
@ObservedObject
View receives an
ObservableObject
包装器使用场景
@State
内部视图状态(必须为
private
),或自有
@Observable
@Binding
子视图修改父视图状态
@Bindable
注入式
@Observable
对象需要绑定
let
来自父视图的只读值
var
通过
.onChange()
监听的只读值
遗留用法(iOS 17之前):
包装器使用场景
@StateObject
视图自有
ObservableObject
(建议使用
@State
结合
@Observable
替代)
@ObservedObject
视图接收的
ObservableObject

Modern API Replacements

现代API替代方案

DeprecatedModern Alternative
foregroundColor()
foregroundStyle()
cornerRadius()
clipShape(.rect(cornerRadius:))
tabItem()
Tab
API (iOS 18+)
onTapGesture()
Button
(unless need location/count)
NavigationView
NavigationStack
onChange(of:) { value in }
onChange(of:) { old, new in }
or
onChange(of:) { }
fontWeight(.bold)
bold()
GeometryReader
containerRelativeFrame()
or
visualEffect()
showsIndicators: false
.scrollIndicators(.hidden)
String(format: "%.2f", value)
Text(value, format: .number.precision(.fractionLength(2)))
string.contains(search)
string.localizedStandardContains(search)
(for user input)
已弃用API现代替代方案
foregroundColor()
foregroundStyle()
cornerRadius()
clipShape(.rect(cornerRadius:))
tabItem()
Tab
API(iOS 18+)
onTapGesture()
Button
(除非需要位置/点击次数)
NavigationView
NavigationStack
onChange(of:) { value in }
onChange(of:) { old, new in }
onChange(of:) { }
fontWeight(.bold)
bold()
GeometryReader
containerRelativeFrame()
visualEffect()
showsIndicators: false
.scrollIndicators(.hidden)
String(format: "%.2f", value)
Text(value, format: .number.precision(.fractionLength(2)))
string.contains(search)
string.localizedStandardContains(search)
(用户输入场景)

Liquid Glass Patterns

Liquid Glass模式

swift
// Basic glass effect with fallback
if #available(iOS 26, *) {
    content
        .padding()
        .glassEffect(.regular.interactive(), in: .rect(cornerRadius: 16))
} else {
    content
        .padding()
        .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 16))
}

// Grouped glass elements
GlassEffectContainer(spacing: 24) {
    HStack(spacing: 24) {
        GlassButton1()
        GlassButton2()
    }
}

// Glass buttons
Button("Confirm") { }
    .buttonStyle(.glassProminent)

swift
// 基础玻璃效果及降级方案
if #available(iOS 26, *) {
    content
        .padding()
        .glassEffect(.regular.interactive(), in: .rect(cornerRadius: 16))
} else {
    content
        .padding()
        .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 16))
}

// 分组玻璃元素
GlassEffectContainer(spacing: 24) {
    HStack(spacing: 24) {
        GlassButton1()
        GlassButton2()
    }
}

// 玻璃按钮
Button("Confirm") { }
    .buttonStyle(.glassProminent)

Review Checklist

评审检查清单

State Management

状态管理

  • Using
    @Observable
    instead of
    ObservableObject
    for new code
  • @Observable
    classes marked with
    @MainActor
    (if needed)
  • Using
    @State
    with
    @Observable
    classes (not
    @StateObject
    )
  • @State
    and
    @StateObject
    properties are
    private
  • Passed values NOT declared as
    @State
    or
    @StateObject
  • @Binding
    only where child modifies parent state
  • @Bindable
    for injected
    @Observable
    needing bindings
  • Nested
    ObservableObject
    avoided (or passed directly to child views)
  • ViewModel used only when testability or complex state warrants it
  • 新代码使用
    @Observable
    而非
    ObservableObject
  • @Observable
    类已标记
    @MainActor
    (若需要)
  • 结合
    @State
    @Observable
    类使用(而非
    @StateObject
  • @State
    @StateObject
    属性已标记为
    private
  • 传入值未被声明为
    @State
    @StateObject
  • 仅在子视图需修改父视图状态时使用
    @Binding
  • 注入式
    @Observable
    对象需要绑定时使用
    @Bindable
  • 已避免嵌套
    ObservableObject
    (或直接传递给子视图)
  • 仅在可测试性或复杂状态需求下使用ViewModel

Modern APIs (see
references/modern-apis.md
)

现代API(详见
references/modern-apis.md

  • Using
    foregroundStyle()
    instead of
    foregroundColor()
  • Using
    clipShape(.rect(cornerRadius:))
    instead of
    cornerRadius()
  • Using
    Tab
    API instead of
    tabItem()
    (iOS 18+)
  • Using
    Button
    instead of
    onTapGesture()
    (unless need location/count)
  • Using
    NavigationStack
    instead of
    NavigationView
  • Avoiding
    UIScreen.main.bounds
  • Using alternatives to
    GeometryReader
    when possible
  • Button images include text labels for accessibility
  • 使用
    foregroundStyle()
    替代
    foregroundColor()
  • 使用
    clipShape(.rect(cornerRadius:))
    替代
    cornerRadius()
  • iOS 18+场景使用
    Tab
    API替代
    tabItem()
  • 使用
    Button
    替代
    onTapGesture()
    (除非需要位置/点击次数)
  • 使用
    NavigationStack
    替代
    NavigationView
  • 避免使用
    UIScreen.main.bounds
  • 有替代方案时避免使用
    GeometryReader
  • 按钮图片包含文本标签以支持无障碍访问

Sheets & Navigation (see
references/navigation-patterns.md
)

Sheets与导航(详见
references/navigation-patterns.md

  • Using
    .sheet(item:)
    for model-based sheets
  • Sheets own their actions and dismiss internally
  • Using
    navigationDestination(for:)
    for type-safe navigation
  • 使用
    .sheet(item:)
    实现基于模型的Sheet
  • Sheet自行管理操作并在内部关闭
  • 使用
    navigationDestination(for:)
    实现类型安全的导航

ScrollView (see
references/scroll-patterns.md
)

ScrollView(详见
references/scroll-patterns.md

  • Using
    ScrollViewReader
    with stable IDs for programmatic scrolling
  • Using
    .scrollIndicators(.hidden)
    instead of initializer parameter
  • 使用
    ScrollViewReader
    结合稳定ID实现程序化滚动
  • 使用
    .scrollIndicators(.hidden)
    替代初始化器参数

Text & Formatting (see
references/text-formatting.md
)

文本与格式化(详见
references/text-formatting.md

  • Using modern Text formatting (not
    String(format:)
    )
  • Using
    localizedStandardContains()
    for search filtering
  • 使用现代文本格式化(而非
    String(format:)
  • 搜索过滤使用
    localizedStandardContains()

View Composition (see
references/view-composition.md
)

视图组合(详见
references/view-composition.md

  • Using modifiers instead of conditionals for state changes
  • Complex views extracted to separate subviews (not
    @ViewBuilder
    functions)
  • Views kept small with one responsibility
  • Container views use
    @ViewBuilder let content: Content
  • Specialized built-ins used where appropriate (Label, GroupBox, Form)
  • Custom styles used to share visual patterns across instances
  • Presentational views prefer primitive parameters (reusability recommendation)
  • 使用修饰符而非条件语句处理状态变化
  • 复杂视图已提取为独立子视图(而非
    @ViewBuilder
    函数)
  • 视图保持轻量化,职责单一
  • 容器视图使用
    @ViewBuilder let content: Content
  • 合适时使用专用原生组件(Label、GroupBox、Form)
  • 使用自定义样式在多个实例间共享视觉模式
  • 展示型视图优先使用原始参数(复用性建议)

Performance (see
references/performance-patterns.md
)

性能(详见
references/performance-patterns.md

  • View
    body
    kept simple and pure (no side effects)
  • Passing only needed values (not large config objects)
  • Eliminating unnecessary dependencies
  • State updates check for value changes before assigning
  • Hot paths minimize state updates
  • No object creation in
    body
  • Heavy computation moved out of
    body
  • 视图
    body
    保持简洁纯净(无副作用)
  • 仅传递所需值(而非大型配置对象)
  • 已消除不必要的依赖
  • 状态更新前先检查值是否变化
  • 热点路径已最小化状态更新
  • body
    中无对象创建操作
  • 重计算逻辑已移出
    body

List Patterns (see
references/list-patterns.md
)

列表模式(详见
references/list-patterns.md

  • ForEach uses stable identity (not
    .indices
    )
  • Constant number of views per ForEach element
  • No inline filtering in ForEach
  • No
    AnyView
    in list rows
  • ForEach使用稳定标识(而非
    .indices
  • ForEach每个元素对应的视图数量恒定
  • 未在ForEach中进行内联过滤
  • 列表行中未使用
    AnyView

Layout (see
references/view-composition.md
)

布局(详见
references/view-composition.md

  • Avoiding layout thrash (deep hierarchies, excessive GeometryReader)
  • Gating frequent geometry updates by thresholds
  • Business logic separated into testable models (when warranted)
  • Action handlers reference methods (not inline logic)
  • Using relative layout (not hard-coded constants)
  • Views work in any context (context-agnostic)
  • 已避免布局抖动(深层层级、过度使用GeometryReader)
  • 频繁几何更新已通过阈值控制
  • 业务逻辑已分离为可测试模型(若需要)
  • 事件处理程序引用方法(而非内联逻辑)
  • 使用相对布局(而非硬编码常量)
  • 视图可适配任意上下文(上下文无关)

Animations (see
references/animation-basics.md
,
references/animation-transitions.md
,
references/animation-advanced.md
)

动画(详见
references/animation-basics.md
references/animation-transitions.md
references/animation-advanced.md

  • Using
    .animation(_:value:)
    with value parameter
  • Using
    withAnimation
    for event-driven animations
  • Transitions paired with animations outside conditional structure
  • Custom
    Animatable
    has explicit
    animatableData
    implementation
  • Preferring transforms over layout changes for animation performance
  • Phase animations for multi-step sequences (iOS 17+)
  • Keyframe animations for precise timing (iOS 17+)
  • Completion handlers use
    .transaction(value:)
    for reexecution
  • 使用带value参数的
    .animation(_:value:)
  • 事件驱动动画使用
    withAnimation
  • 过渡动画已在条件结构外部设置
  • 自定义
    Animatable
    包含显式
    animatableData
    实现
  • 优先使用变换而非布局变化提升动画性能
  • iOS 17+多步序列动画使用Phase动画
  • 需要精确时间控制的动画使用关键帧动画
  • 动画完成处理程序使用
    .transaction(value:)
    以支持重新执行

Liquid Glass (iOS 26+)

Liquid Glass(iOS 26+)

  • #available(iOS 26, *)
    with fallback for Liquid Glass
  • Multiple glass views wrapped in
    GlassEffectContainer
  • .glassEffect()
    applied after layout/appearance modifiers
  • .interactive()
    only on user-interactable elements
  • Shapes and tints consistent across related elements

  • 已使用
    #available(iOS 26, *)
    并提供降级方案
  • 多个玻璃元素已包裹在
    GlassEffectContainer
  • .glassEffect()
    已在布局/外观修饰符之后应用
  • .interactive()
    仅用于用户可交互元素
  • 相关元素的形状和色调保持一致

References

参考文档

  • references/state-management.md
    — Property wrappers, data flow, when to use a ViewModel
  • references/view-composition.md
    — View extraction, styles, specialized views, reusability
  • references/performance-patterns.md
    — Performance optimization techniques and anti-patterns
  • references/list-patterns.md
    — ForEach identity, stability, and list best practices
  • references/modern-apis.md
    — Modern API usage and deprecated replacements
  • references/animation-basics.md
    — Core animation concepts, implicit/explicit animations
  • references/animation-transitions.md
    — Transitions, custom transitions, Animatable protocol
  • references/animation-advanced.md
    — Transactions, phase/keyframe animations, completion handlers
  • references/navigation-patterns.md
    — Sheet presentation and navigation patterns
  • references/scroll-patterns.md
    — ScrollView patterns and programmatic scrolling
  • references/text-formatting.md
    — Modern text formatting and string operations
  • references/image-optimization.md
    — AsyncImage, image downsampling, and optimization
  • references/liquid-glass.md
    — iOS 26+ Liquid Glass API (adopt only when explicitly requested)

  • references/state-management.md
    — 属性包装器、数据流、何时使用ViewModel
  • references/view-composition.md
    — 视图提取、样式、专用视图、复用性
  • references/performance-patterns.md
    — 性能优化技术与反模式
  • references/list-patterns.md
    — ForEach标识、稳定性与列表最佳实践
  • references/modern-apis.md
    — 现代API使用与已弃用API替代方案
  • references/animation-basics.md
    — 核心动画概念、隐式/显式动画
  • references/animation-transitions.md
    — 过渡动画、自定义过渡、Animatable协议
  • references/animation-advanced.md
    — 事务、阶段/关键帧动画、完成处理程序
  • references/navigation-patterns.md
    — Sheet展示与导航模式
  • references/scroll-patterns.md
    — ScrollView模式与程序化滚动
  • references/text-formatting.md
    — 现代文本格式化与字符串操作
  • references/image-optimization.md
    — AsyncImage、图片下采样与优化
  • references/liquid-glass.md
    — iOS 26+ Liquid Glass API(仅在明确要求时采用)

Philosophy

理念

This skill focuses on facts and best practices, not architectural opinions:
  • We don't enforce specific architectures (e.g., MVVM, VIPER) — see
    architecture-design-skill
  • We do encourage separating business logic for testability when warranted
  • We prioritize modern APIs over deprecated ones
  • We emphasize thread safety with
    @MainActor
    and
    @Observable
  • We optimize for performance and maintainability
  • We follow Apple's Human Interface Guidelines and API design patterns
  • We use "prefer"/"avoid" for recommendations; "always"/"never" only for correctness of API
本技能专注于事实与最佳实践,而非架构观点:
  • 不强制特定架构(如MVVM、VIPER)——请参考
    architecture-design-skill
  • 但会在需要时鼓励分离业务逻辑以提升可测试性
  • 优先使用现代API而非已弃用API
  • 强调通过
    @MainActor
    @Observable
    保证线程安全
  • 优化性能与可维护性
  • 遵循Apple的人机界面指南与API设计模式
  • 使用“优先/避免”给出建议;仅在API正确性上使用“始终/绝不”",