apple-hig-designer

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Apple HIG Designer

Apple HIG 设计指南

Design beautiful, native iOS apps following Apple's Human Interface Guidelines (HIG). Create accessible, intuitive interfaces with native components, proper typography, semantic colors, and Apple's design principles.
遵循苹果人机界面指南(HIG)设计美观、原生的iOS应用。使用原生组件、合适的排版、语义化颜色和苹果设计原则,创建无障碍、直观的界面。

What This Skill Does

此技能的功能

Helps you design and build iOS apps that feel native and follow Apple's guidelines:
  • Generate iOS Components - Create SwiftUI and UIKit components
  • Validate Designs - Check compliance with Apple HIG
  • Ensure Accessibility - VoiceOver, Dynamic Type, color contrast
  • Apply Design Principles - Clarity, Deference, Depth
  • Use Semantic Colors - Automatic dark mode support
  • Implement Typography - San Francisco font system
  • Follow Spacing - 8pt grid system and safe areas
帮助你设计和构建符合苹果指南的原生iOS应用:
  • 生成iOS组件 - 创建SwiftUI和UIKit组件
  • 验证设计合规性 - 检查是否符合Apple HIG
  • 确保无障碍性 - VoiceOver、Dynamic Type、颜色对比度
  • 应用设计原则 - 清晰、顺从、深度
  • 使用语义化颜色 - 自动支持深色模式
  • 实现排版规范 - San Francisco字体系统
  • 遵循间距规则 - 8pt网格系统和安全区域

Apple's Design Principles

苹果的设计原则

1. Clarity

1. 清晰(Clarity)

Make content clear and focused.
Text is legible at every size, icons are precise and lucid, adornments are subtle and appropriate, and a focus on functionality drives the design.
swift
// ✅ Clear, focused content
Text("Welcome back, Sarah")
    .font(.title)
    .foregroundColor(.primary)

// ❌ Unclear, cluttered
Text("Welcome back, Sarah!!!")
    .font(.title)
    .foregroundColor(.red)
    .background(.yellow)
    .overlay(Image(systemName: "star.fill"))
让内容清晰且聚焦。
文本在任何尺寸下都清晰易读,图标精准易懂,装饰元素简洁恰当,设计以功能为核心。
swift
// ✅ 清晰、聚焦的内容
Text("Welcome back, Sarah")
    .font(.title)
    .foregroundColor(.primary)

// ❌ 模糊、杂乱的内容
Text("Welcome back, Sarah!!!")
    .font(.title)
    .foregroundColor(.red)
    .background(.yellow)
    .overlay(Image(systemName: "star.fill"))

2. Deference

2. 顺从(Deference)

UI helps people understand and interact with content, but never competes with it.
The interface defers to content, using a light visual treatment that keeps focus on the content and gives the content room to breathe.
swift
// ✅ Content-focused
VStack(alignment: .leading, spacing: 8) {
    Text("Article Title")
        .font(.headline)
    Text("Article content goes here...")
        .font(.body)
        .foregroundColor(.secondary)
}
.padding()

// ❌ Distracting UI
VStack(spacing: 8) {
    Text("Article Title")
        .font(.headline)
        .foregroundColor(.white)
        .background(.blue)
        .border(.red, width: 3)
}
界面帮助用户理解和交互内容,但绝不与内容竞争注意力。
界面顺从于内容,采用轻量化视觉处理,让焦点始终在内容上,为内容留出呼吸空间。
swift
// ✅ 以内容为核心
VStack(alignment: .leading, spacing: 8) {
    Text("Article Title")
        .font(.headline)
    Text("Article content goes here...")
        .font(.body)
        .foregroundColor(.secondary)
}
.padding()

// ❌ 分散注意力的界面
VStack(spacing: 8) {
    Text("Article Title")
        .font(.headline)
        .foregroundColor(.white)
        .background(.blue)
        .border(.red, width: 3)
}

3. Depth

3. 深度(Depth)

Visual layers and realistic motion convey hierarchy and help people understand relationships.
Distinct visual layers and realistic motion impart vitality and facilitate understanding. Touch and discoverability heighten delight and enable access to functionality without losing context.
swift
// ✅ Clear depth hierarchy
ZStack {
    Color(.systemBackground)

    VStack {
        // Card with elevation
        CardView()
            .shadow(radius: 8)
    }
}

// Using blur for depth
Text("Content")
    .background(.ultraThinMaterial)
视觉层级和真实的动效传达结构关系,帮助用户理解元素间的关联。
清晰的视觉层级和真实的动效赋予界面活力,便于用户理解。触控和可发现性提升愉悦感,让用户无需脱离上下文即可访问功能。
swift
// ✅ 清晰的深度层级
ZStack {
    Color(.systemBackground)

    VStack {
        // 带阴影的卡片
        CardView()
            .shadow(radius: 8)
    }
}

// 使用模糊效果营造深度
Text("Content")
    .background(.ultraThinMaterial)

iOS UI Components

iOS UI组件

Navigation Patterns

导航模式

1. Navigation Bar

1. 导航栏(Navigation Bar)

Top bar for navigation and actions.
swift
NavigationStack {
    List {
        Text("Item 1")
        Text("Item 2")
    }
    .navigationTitle("Title")
    .navigationBarTitleDisplayMode(.large)
    .toolbar {
        ToolbarItem(placement: .navigationBarTrailing) {
            Button("Add") {
                // Action
            }
        }
    }
}
Guidelines:
  • Use large titles for top-level views
  • Use inline titles for detail views
  • Keep actions relevant to current context
  • Maximum 2-3 toolbar items
顶部导航和操作栏。
swift
NavigationStack {
    List {
        Text("Item 1")
        Text("Item 2")
    }
    .navigationTitle("Title")
    .navigationBarTitleDisplayMode(.large)
    .toolbar {
        ToolbarItem(placement: .navigationBarTrailing) {
            Button("Add") {
                // 操作
            }
        }
    }
}
设计指南:
  • 顶级视图使用大标题
  • 详情视图使用内联标题
  • 操作按钮需与当前上下文相关
  • 工具栏最多保留2-3个按钮

2. Tab Bar

2. 标签栏(Tab Bar)

Bottom navigation for top-level destinations.
swift
TabView {
    HomeView()
        .tabItem {
            Label("Home", systemImage: "house")
        }

    SearchView()
        .tabItem {
            Label("Search", systemImage: "magnifyingglass")
        }

    ProfileView()
        .tabItem {
            Label("Profile", systemImage: "person")
        }
}
Guidelines:
  • 3-5 tabs maximum
  • Use SF Symbols for icons
  • Labels should be concise (one word)
  • Never hide or disable tabs
  • Don't use tab bar with toolbar in same view
底部导航栏,用于顶级目的地切换。
swift
TabView {
    HomeView()
        .tabItem {
            Label("Home", systemImage: "house")
        }

    SearchView()
        .tabItem {
            Label("Search", systemImage: "magnifyingglass")
        }

    ProfileView()
        .tabItem {
            Label("Profile", systemImage: "person")
        }
}
设计指南:
  • 最多3-5个标签
  • 使用SF Symbols图标
  • 标签文字简洁(单个单词)
  • 绝不隐藏或禁用标签
  • 同一视图中不要同时使用标签栏和工具栏

3. List

3. 列表(List)

Scrollable list of items.
swift
List {
    Section("Today") {
        ForEach(items) { item in
            NavigationLink {
                DetailView(item: item)
            } label: {
                HStack {
                    Image(systemName: item.icon)
                        .foregroundColor(.accentColor)
                    Text(item.title)
                }
            }
        }
    }
}
.listStyle(.insetGrouped)
List Styles:
  • .plain
    - Edge-to-edge rows
  • .insetGrouped
    - Rounded, inset sections (iOS default)
  • .sidebar
    - For navigation sidebars
可滚动的项目列表。
swift
List {
    Section("Today") {
        ForEach(items) { item in
            NavigationLink {
                DetailView(item: item)
            } label: {
                HStack {
                    Image(systemName: item.icon)
                        .foregroundColor(.accentColor)
                    Text(item.title)
                }
            }
        }
    }
}
.listStyle(.insetGrouped)
列表样式:
  • .plain
    - 边缘对齐的行
  • .insetGrouped
    - 圆角内嵌分组(iOS默认样式)
  • .sidebar
    - 用于导航侧边栏

4. Sheet (Modal)

4. 模态弹窗(Sheet)

Present content modally.
swift
struct ContentView: View {
    @State private var showSheet = false

    var body: some View {
        Button("Show Details") {
            showSheet = true
        }
        .sheet(isPresented: $showSheet) {
            DetailView()
                .presentationDetents([.medium, .large])
        }
    }
}
Sheet Detents:
  • .medium
    - Half screen
  • .large
    - Full screen
  • Custom heights available
以模态方式展示内容。
swift
struct ContentView: View {
    @State private var showSheet = false

    var body: some View {
        Button("Show Details") {
            showSheet = true
        }
        .sheet(isPresented: $showSheet) {
            DetailView()
                .presentationDetents([.medium, .large])
        }
    }
}
弹窗尺寸:
  • .medium
    - 半屏
  • .large
    - 全屏
  • 支持自定义高度

Form Controls

表单控件

1. Button

1. 按钮(Button)

Primary action control.
swift
// Filled button (primary action)
Button("Continue") {
    // Action
}
.buttonStyle(.borderedProminent)

// Bordered button (secondary action)
Button("Cancel") {
    // Action
}
.buttonStyle(.bordered)

// Plain button (tertiary action)
Button("Learn More") {
    // Action
}
.buttonStyle(.plain)
Button Hierarchy:
  1. Prominent - Primary action (one per screen)
  2. Bordered - Secondary actions
  3. Plain - Tertiary actions, links
Guidelines:
  • Minimum tap target: 44x44 points
  • Use verbs for button labels
  • Make destructive actions require confirmation
主要操作控件。
swift
// 填充按钮(主要操作)
Button("Continue") {
    // 操作
}
.buttonStyle(.borderedProminent)

// 边框按钮(次要操作)
Button("Cancel") {
    // 操作
}
.buttonStyle(.bordered)

// 纯文本按钮( tertiary操作)
Button("Learn More") {
    // 操作
}
.buttonStyle(.plain)
按钮层级:
  1. Prominent - 主要操作(每个屏幕最多一个)
  2. Bordered - 次要操作
  3. Plain - tertiary操作、链接
设计指南:
  • 最小点击区域:44x44点
  • 按钮标签使用动词
  • 破坏性操作需确认

2. TextField

2. 文本输入框(TextField)

Text input control.
swift
@State private var username = ""
@State private var password = ""

VStack(alignment: .leading, spacing: 16) {
    // Standard text field
    TextField("Username", text: $username)
        .textFieldStyle(.roundedBorder)
        .textContentType(.username)
        .textInputAutocapitalization(.never)
        .autocorrectionDisabled()

    // Secure field
    SecureField("Password", text: $password)
        .textFieldStyle(.roundedBorder)
        .textContentType(.password)
}
Text Content Types:
  • .username
    - Username field
  • .password
    - Password field
  • .emailAddress
    - Email field
  • .telephoneNumber
    - Phone number
  • .creditCardNumber
    - Credit card
文本输入控件。
swift
@State private var username = ""
@State private var password = ""

VStack(alignment: .leading, spacing: 16) {
    // 标准文本输入框
    TextField("Username", text: $username)
        .textFieldStyle(.roundedBorder)
        .textContentType(.username)
        .textInputAutocapitalization(.never)
        .autocorrectionDisabled()

    // 密码输入框
    SecureField("Password", text: $password)
        .textFieldStyle(.roundedBorder)
        .textContentType(.password)
}
文本内容类型:
  • .username
    - 用户名输入框
  • .password
    - 密码输入框
  • .emailAddress
    - 邮箱输入框
  • .telephoneNumber
    - 电话号码输入框
  • .creditCardNumber
    - 信用卡输入框

3. Toggle

3. 开关控件(Toggle)

Boolean control (switch).
swift
@State private var isEnabled = false

Toggle("Enable notifications", isOn: $isEnabled)
    .toggleStyle(.switch)
Guidelines:
  • Label describes what the toggle controls
  • Effect should be immediate
  • Use for binary choices only
布尔值控件(开关)。
swift
@State private var isEnabled = false

Toggle("Enable notifications", isOn: $isEnabled)
    .toggleStyle(.switch)
设计指南:
  • 标签需说明开关控制的功能
  • 效果需即时生效
  • 仅用于二元选择

4. Picker

4. 选择器(Picker)

Selection control.
swift
@State private var selectedSize = "Medium"
let sizes = ["Small", "Medium", "Large"]

// Menu style
Picker("Size", selection: $selectedSize) {
    ForEach(sizes, id: \.self) { size in
        Text(size).tag(size)
    }
}
.pickerStyle(.menu)

// Segmented style (for 2-5 options)
Picker("Size", selection: $selectedSize) {
    ForEach(sizes, id: \.self) { size in
        Text(size).tag(size)
    }
}
.pickerStyle(.segmented)
Picker Styles:
  • .menu
    - Dropdown menu (default)
  • .segmented
    - Segmented control (2-5 options)
  • .wheel
    - Scrollable wheel
  • .inline
    - Inline list (in forms)
选择控件。
swift
@State private var selectedSize = "Medium"
let sizes = ["Small", "Medium", "Large"]

// 菜单样式
Picker("Size", selection: $selectedSize) {
    ForEach(sizes, id: \.self) { size in
        Text(size).tag(size)
    }
}
.pickerStyle(.menu)

// 分段样式(适用于2-5个选项)
Picker("Size", selection: $selectedSize) {
    ForEach(sizes, id: \.self) { size in
        Text(size).tag(size)
    }
}
.pickerStyle(.segmented)
选择器样式:
  • .menu
    - 下拉菜单(默认)
  • .segmented
    - 分段控件(2-5个选项)
  • .wheel
    - 可滚动滚轮
  • .inline
    - 内联列表(用于表单)

Cards and Containers

卡片和容器

Card View

卡片视图(Card View)

swift
struct CardView: View {
    var body: some View {
        VStack(alignment: .leading, spacing: 12) {
            Text("Title")
                .font(.headline)

            Text("Description goes here with some details about the content.")
                .font(.subheadline)
                .foregroundColor(.secondary)
                .lineLimit(2)

            Spacer()

            Button("Action") {
                // Action
            }
            .buttonStyle(.borderedProminent)
        }
        .padding()
        .frame(width: 300, height: 200)
        .background(Color(.systemBackground))
        .cornerRadius(12)
        .shadow(color: .black.opacity(0.1), radius: 8, x: 0, y: 4)
    }
}
swift
struct CardView: View {
    var body: some View {
        VStack(alignment: .leading, spacing: 12) {
            Text("Title")
                .font(.headline)

            Text("Description goes here with some details about the content.")
                .font(.subheadline)
                .foregroundColor(.secondary)
                .lineLimit(2)

            Spacer()

            Button("Action") {
                // 操作
            }
            .buttonStyle(.borderedProminent)
        }
        .padding()
        .frame(width: 300, height: 200)
        .background(Color(.systemBackground))
        .cornerRadius(12)
        .shadow(color: .black.opacity(0.1), radius: 8, x: 0, y: 4)
    }
}

Typography

排版

San Francisco Font System

San Francisco 字体系统

Apple's system font designed for optimal legibility.
swift
// Dynamic Type text styles
Text("Large Title").font(.largeTitle)      // 34pt
Text("Title").font(.title)                 // 28pt
Text("Title 2").font(.title2)              // 22pt
Text("Title 3").font(.title3)              // 20pt
Text("Headline").font(.headline)           // 17pt semibold
Text("Body").font(.body)                   // 17pt regular
Text("Callout").font(.callout)             // 16pt
Text("Subheadline").font(.subheadline)     // 15pt
Text("Footnote").font(.footnote)           // 13pt
Text("Caption").font(.caption)             // 12pt
Text("Caption 2").font(.caption2)          // 11pt
苹果为最佳可读性设计的系统字体。
swift
// Dynamic Type 文本样式
Text("Large Title").font(.largeTitle)      // 34pt
Text("Title").font(.title)                 // 28pt
Text("Title 2").font(.title2)              // 22pt
Text("Title 3").font(.title3)              // 20pt
Text("Headline").font(.headline)           // 17pt semibold
Text("Body").font(.body)                   // 17pt regular
Text("Callout").font(.callout)             // 16pt
Text("Subheadline").font(.subheadline)     // 15pt
Text("Footnote").font(.footnote)           // 13pt
Text("Caption").font(.caption)             // 12pt
Text("Caption 2").font(.caption2)          // 11pt

Custom Fonts with Dynamic Type

支持Dynamic Type的自定义字体

swift
// Custom font that scales with Dynamic Type
Text("Custom Text")
    .font(.custom("YourFont-Regular", size: 17, relativeTo: .body))
swift
// 随Dynamic Type缩放的自定义字体
Text("Custom Text")
    .font(.custom("YourFont-Regular", size: 17, relativeTo: .body))

Font Weights

字体粗细

swift
Text("Light").fontWeight(.light)
Text("Regular").fontWeight(.regular)
Text("Medium").fontWeight(.medium)
Text("Semibold").fontWeight(.semibold)
Text("Bold").fontWeight(.bold)
Text("Heavy").fontWeight(.heavy)
swift
Text("Light").fontWeight(.light)
Text("Regular").fontWeight(.regular)
Text("Medium").fontWeight(.medium)
Text("Semibold").fontWeight(.semibold)
Text("Bold").fontWeight(.bold)
Text("Heavy").fontWeight(.heavy)

Typography Guidelines

排版指南

Do:
  • ✅ Use system font (San Francisco) for consistency
  • ✅ Support Dynamic Type for accessibility
  • ✅ Use semantic text styles (.headline, .body, etc.)
  • ✅ Minimum body text: 17pt
  • ✅ Line spacing: 120-145% of font size
Don't:
  • ❌ Use too many font sizes (stick to system styles)
  • ❌ Make text smaller than 11pt
  • ❌ Use all caps for long text
  • ❌ Disable Dynamic Type
建议:
  • ✅ 使用系统字体(San Francisco)以保证一致性
  • ✅ 支持Dynamic Type以提升无障碍性
  • ✅ 使用语义化文本样式(.headline、.body等)
  • ✅ 正文最小字号:17pt
  • ✅ 行间距:字号的120-145%
避免:
  • ❌ 使用过多字体尺寸(遵循系统样式)
  • ❌ 文本小于11pt
  • ❌ 长文本使用全大写
  • ❌ 禁用Dynamic Type

Colors

颜色

Semantic Colors

语义化颜色

Colors that automatically adapt to light/dark mode.
swift
// UI Element Colors
Color(.label)                    // Primary text
Color(.secondaryLabel)           // Secondary text
Color(.tertiaryLabel)            // Tertiary text
Color(.quaternaryLabel)          // Watermark text

Color(.systemBackground)         // Primary background
Color(.secondarySystemBackground) // Secondary background
Color(.tertiarySystemBackground)  // Tertiary background

Color(.systemFill)               // Fill colors
Color(.secondarySystemFill)
Color(.tertiarySystemFill)
Color(.quaternarySystemFill)

Color(.separator)                // Separator lines
Color(.opaqueSeparator)          // Non-transparent separator
自动适配亮色/深色模式的颜色。
swift
// UI元素颜色
Color(.label)                    // 主文本色
Color(.secondaryLabel)           // 次要文本色
Color(.tertiaryLabel)            // 三级文本色
Color(.quaternaryLabel)          // 水印文本色

Color(.systemBackground)         // 主背景色
Color(.secondarySystemBackground) // 次要背景色
Color(.tertiarySystemBackground)  // 三级背景色

Color(.systemFill)               // 填充色
Color(.secondarySystemFill)
Color(.tertiarySystemFill)
Color(.quaternarySystemFill)

Color(.separator)                // 分隔线
Color(.opaqueSeparator)          // 不透明分隔线

System Colors

系统颜色

swift
// Standard system colors (adapt to dark mode)
Color(.systemRed)
Color(.systemOrange)
Color(.systemYellow)
Color(.systemGreen)
Color(.systemMint)
Color(.systemTeal)
Color(.systemCyan)
Color(.systemBlue)
Color(.systemIndigo)
Color(.systemPurple)
Color(.systemPink)
Color(.systemBrown)
Color(.systemGray)
swift
// 标准系统颜色(自动适配深色模式)
Color(.systemRed)
Color(.systemOrange)
Color(.systemYellow)
Color(.systemGreen)
Color(.systemMint)
Color(.systemTeal)
Color(.systemCyan)
Color(.systemBlue)
Color(.systemIndigo)
Color(.systemPurple)
Color(.systemPink)
Color(.systemBrown)
Color(.systemGray)

Custom Colors with Dark Mode

支持深色模式的自定义颜色

swift
// Define adaptive color
extension Color {
    static let customBackground = Color("CustomBackground")
}

// In Assets.xcassets, create color set with:
// - Any Appearance: #FFFFFF
// - Dark Appearance: #000000
swift
// 定义自适应颜色
extension Color {
    static let customBackground = Color("CustomBackground")
}

// 在Assets.xcassets中创建颜色集:
// - 通用外观:#FFFFFF
// - 深色外观:#000000

Color Contrast Guidelines

颜色对比度指南

WCAG AA Compliance:
  • Normal text: 4.5:1 contrast ratio minimum
  • Large text (24pt+): 3:1 contrast ratio minimum
  • UI components: 3:1 contrast ratio
Custom colors:
  • Test with Increase Contrast enabled
  • Aim for 7:1 for critical text
  • Provide sufficient contrast in both modes
WCAG AA合规要求:
  • 普通文本:最小对比度4.5:1
  • 大文本(24pt+):最小对比度3:1
  • UI组件:最小对比度3:1
自定义颜色:
  • 开启增强对比度模式测试
  • 关键文本目标对比度7:1
  • 确保两种模式下都有足够对比度

Spacing and Layout

间距与布局

8-Point Grid System

8点网格系统

All spacing should be multiples of 8.
swift
// Spacing values
.padding(8)      // 8pt
.padding(16)     // 16pt (standard)
.padding(24)     // 24pt
.padding(32)     // 32pt
.padding(40)     // 40pt
.padding(48)     // 48pt

// Edge-specific padding
.padding(.horizontal, 16)
.padding(.vertical, 24)
.padding(.top, 16)
.padding(.bottom, 16)
所有间距应为8的倍数。
swift
// 间距值
.padding(8)      // 8pt
.padding(16)     // 16pt(标准)
.padding(24)     // 24pt
.padding(32)     // 32pt
.padding(40)     // 40pt
.padding(48)     // 48pt

// 边缘特定间距
.padding(.horizontal, 16)
.padding(.vertical, 24)
.padding(.top, 16)
.padding(.bottom, 16)

Safe Areas

安全区域

Respect device safe areas.
swift
// Content within safe area (default)
VStack {
    Text("Content")
}

// Extend beyond safe area
VStack {
    Color.blue
}
.ignoresSafeArea()

// Extend top only
VStack {
    Color.blue
}
.ignoresSafeArea(edges: .top)
尊重设备安全区域。
swift
// 内容在安全区域内(默认)
VStack {
    Text("Content")
}

// 超出安全区域
VStack {
    Color.blue
}
.ignoresSafeArea()

// 仅顶部超出安全区域
VStack {
    Color.blue
}
.ignoresSafeArea(edges: .top)

Touch Targets

点击区域

Minimum interactive size: 44x44 points.
swift
Button("Tap") {
    // Action
}
.frame(minWidth: 44, minHeight: 44)
最小交互尺寸:44x44点。
swift
Button("Tap") {
    // 操作
}
.frame(minWidth: 44, minHeight: 44)

Spacing Guidelines

间距指南

swift
// Component spacing
VStack(spacing: 8) {       // Tight spacing
    Text("Line 1")
    Text("Line 2")
}

VStack(spacing: 16) {      // Standard spacing
    Text("Section 1")
    Text("Section 2")
}

VStack(spacing: 24) {      // Loose spacing
    SectionView()
    SectionView()
}
swift
// 组件间距
VStack(spacing: 8) {       // 紧凑间距
    Text("Line 1")
    Text("Line 2")
}

VStack(spacing: 16) {      // 标准间距
    Text("Section 1")
    Text("Section 2")
}

VStack(spacing: 24) {      // 宽松间距
    SectionView()
    SectionView()
}

Accessibility

无障碍性

VoiceOver Support

VoiceOver 支持

Screen reader for blind and low-vision users.
swift
// Accessible label
Image(systemName: "heart.fill")
    .accessibilityLabel("Favorite")

// Accessible value
Slider(value: $volume)
    .accessibilityLabel("Volume")
    .accessibilityValue("\(Int(volume * 100))%")

// Accessible hint
Button("Share") {
    share()
}
.accessibilityHint("Shares this item with others")

// Group elements
HStack {
    Image(systemName: "person")
    Text("John Doe")
}
.accessibilityElement(children: .combine)

// Hidden from VoiceOver
Image("decorative")
    .accessibilityHidden(true)
为盲人和低视力用户设计的屏幕阅读器。
swift
// 无障碍标签
Image(systemName: "heart.fill")
    .accessibilityLabel("Favorite")

// 无障碍值
Slider(value: $volume)
    .accessibilityLabel("Volume")
    .accessibilityValue("\(Int(volume * 100))%")

// 无障碍提示
Button("Share") {
    share()
}
.accessibilityHint("Shares this item with others")

// 组合元素
HStack {
    Image(systemName: "person")
    Text("John Doe")
}
.accessibilityElement(children: .combine)

// 对VoiceOver隐藏
Image("decorative")
    .accessibilityHidden(true)

Dynamic Type

Dynamic Type 支持

Support user's preferred text size.
swift
// Automatically supported with system fonts
Text("This text scales")
    .font(.body)

// Limit scaling (if necessary)
Text("This text has limits")
    .font(.body)
    .dynamicTypeSize(...DynamicTypeSize.xxxLarge)

// Custom font with Dynamic Type
Text("Custom font")
    .font(.custom("YourFont", size: 17, relativeTo: .body))
支持用户偏好的文本尺寸。
swift
// 系统字体自动支持
Text("This text scales")
    .font(.body)

// 限制缩放(必要时)
Text("This text has limits")
    .font(.body)
    .dynamicTypeSize(...DynamicTypeSize.xxxLarge)

// 支持Dynamic Type的自定义字体
Text("Custom font")
    .font(.custom("YourFont", size: 17, relativeTo: .body))

Color Blindness

色盲友好设计

Design for color-blind users.
swift
// Don't rely on color alone
HStack {
    Image(systemName: "checkmark.circle.fill")
        .foregroundColor(.green)
    Text("Success")
}

// Not just color
Circle()
    .fill(.green)
// ❌ Color only

// Better with shape/icon
HStack {
    Image(systemName: "checkmark.circle.fill")
    Circle().fill(.green)
}
// ✅ Color + shape
为色盲用户设计。
swift
// 不要仅依赖颜色
HStack {
    Image(systemName: "checkmark.circle.fill")
        .foregroundColor(.green)
    Text("Success")
}

// 仅用颜色 ❌
Circle()
    .fill(.green)

// 颜色+形状/图标 ✅
HStack {
    Image(systemName: "checkmark.circle.fill")
    Circle().fill(.green)
}

Reduce Motion

减少动效

Respect user's motion preferences.
swift
@Environment(\.accessibilityReduceMotion) var reduceMotion

var animation: Animation {
    reduceMotion ? .none : .spring()
}

Button("Animate") {
    withAnimation(animation) {
        // Animate
    }
}
尊重用户的动效偏好。
swift
@Environment(\.accessibilityReduceMotion) var reduceMotion

var animation: Animation {
    reduceMotion ? .none : .spring()
}

Button("Animate") {
    withAnimation(animation) {
        // 动画
    }
}

Increase Contrast

增强对比度

Support high contrast mode.
swift
@Environment(\.colorSchemeContrast) var contrast

var textColor: Color {
    contrast == .increased ? .primary : .secondary
}

Text("Content")
    .foregroundColor(textColor)
支持高对比度模式。
swift
@Environment(\.colorSchemeContrast) var contrast

var textColor: Color {
    contrast == .increased ? .primary : .secondary
}

Text("Content")
    .foregroundColor(textColor)

Dark Mode

深色模式

Support both light and dark appearances.
支持亮色和深色外观。

Automatic Support

自动支持

swift
// Use semantic colors (automatic)
Color(.label)                // Adapts automatically
Color(.systemBackground)     // Adapts automatically
swift
// 使用语义化颜色(自动适配)
Color(.label)                // 自动适配
Color(.systemBackground)     // 自动适配

Testing Dark Mode

测试深色模式

swift
// Preview both modes
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
            .preferredColorScheme(.light)

        ContentView()
            .preferredColorScheme(.dark)
    }
}
swift
// 预览两种模式
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
            .preferredColorScheme(.light)

        ContentView()
            .preferredColorScheme(.dark)
    }
}

Dark Mode Guidelines

深色模式指南

Do:
  • ✅ Use semantic colors
  • ✅ Test with Increase Contrast
  • ✅ Test with Reduce Transparency
  • ✅ Ensure sufficient contrast in both modes
Don't:
  • ❌ Use pure black (#000000) - use systemBackground
  • ❌ Invert colors automatically
  • ❌ Assume user preference
建议:
  • ✅ 使用语义化颜色
  • ✅ 开启增强对比度测试
  • ✅ 开启减少透明度测试
  • ✅ 确保两种模式下都有足够对比度
避免:
  • ❌ 使用纯黑色(#000000)- 使用systemBackground
  • ❌ 自动反转颜色
  • ❌ 假设用户偏好

SF Symbols

SF Symbols

Apple's icon system (3000+ symbols).
swift
// Basic symbol
Image(systemName: "heart")

// Colored symbol
Image(systemName: "heart.fill")
    .foregroundColor(.red)

// Sized symbol
Image(systemName: "heart")
    .imageScale(.large)

// Font-based sizing
Image(systemName: "heart")
    .font(.title)

// Multicolor symbols
Image(systemName: "person.crop.circle.fill.badge.checkmark")
    .symbolRenderingMode(.multicolor)

// Hierarchical rendering
Image(systemName: "heart.fill")
    .symbolRenderingMode(.hierarchical)
    .foregroundColor(.red)
苹果的图标系统(3000+图标)。
swift
// 基础图标
Image(systemName: "heart")

// 带颜色的图标
Image(systemName: "heart.fill")
    .foregroundColor(.red)

// 调整大小的图标
Image(systemName: "heart")
    .imageScale(.large)

// 基于字体的尺寸
Image(systemName: "heart")
    .font(.title)

// 多色图标
Image(systemName: "person.crop.circle.fill.badge.checkmark")
    .symbolRenderingMode(.multicolor)

// 层级渲染
Image(systemName: "heart.fill")
    .symbolRenderingMode(.hierarchical)
    .foregroundColor(.red)

SF Symbols Guidelines

SF Symbols 指南

  • Use system symbols when available
  • Maintain visual weight consistency
  • Use multicolor for semantic meaning
  • Size appropriately for context
  • 优先使用系统图标
  • 保持视觉权重一致
  • 多色图标用于语义化表达
  • 根据上下文调整尺寸

App Icons

应用图标

Icon Sizes

图标尺寸

iOS:
- 1024x1024 (App Store)
- 180x180 (iPhone @3x)
- 120x120 (iPhone @2x)
- 167x167 (iPad Pro)
- 152x152 (iPad @2x)

watchOS:
- 1024x1024 (App Store)
- 196x196 (49mm)
- 216x216 (45mm)
iOS:
- 1024x1024 (App Store)
- 180x180 (iPhone @3x)
- 120x120 (iPhone @2x)
- 167x167 (iPad Pro)
- 152x152 (iPad @2x)

watchOS:
- 1024x1024 (App Store)
- 196x196 (49mm)
- 216x216 (45mm)

Icon Design Guidelines

图标设计指南

Do:
  • ✅ Use simple, recognizable shapes
  • ✅ Fill entire icon space
  • ✅ Test on device (not just mockups)
  • ✅ Use consistent visual style
Don't:
  • ❌ Include text (very small)
  • ❌ Use photos
  • ❌ Replicate Apple hardware
  • ❌ Use translucency
建议:
  • ✅ 使用简单、可识别的形状
  • ✅ 填满整个图标空间
  • ✅ 在设备上测试(不只是原型)
  • ✅ 保持视觉风格一致
避免:
  • ❌ 包含文字(尺寸太小)
  • ❌ 使用照片
  • ❌ 模仿苹果硬件
  • ❌ 使用半透明效果

Animation and Motion

动画与动效

Standard Animations

标准动画

swift
// Spring animation (natural, bouncy)
withAnimation(.spring()) {
    offset = 100
}

// Linear animation
withAnimation(.linear(duration: 0.3)) {
    opacity = 0
}

// Ease in/out
withAnimation(.easeInOut(duration: 0.3)) {
    scale = 1.2
}
swift
// 弹簧动画(自然、有弹性)
withAnimation(.spring()) {
    offset = 100
}

// 线性动画
withAnimation(.linear(duration: 0.3)) {
    opacity = 0
}

// 缓入缓出动画
withAnimation(.easeInOut(duration: 0.3)) {
    scale = 1.2
}

Gesture-Driven

手势驱动动画

swift
@State private var offset = CGSize.zero

var body: some View {
    Circle()
        .offset(offset)
        .gesture(
            DragGesture()
                .onChanged { value in
                    offset = value.translation
                }
                .onEnded { _ in
                    withAnimation(.spring()) {
                        offset = .zero
                    }
                }
        )
}
swift
@State private var offset = CGSize.zero

var body: some View {
    Circle()
        .offset(offset)
        .gesture(
            DragGesture()
                .onChanged { value in
                    offset = value.translation
                }
                .onEnded { _ in
                    withAnimation(.spring()) {
                        offset = .zero
                    }
                }
        )
}

Motion Guidelines

动效指南

  • Keep animations under 0.3 seconds
  • Use spring animations for interactive elements
  • Respect Reduce Motion setting
  • Provide visual feedback for all interactions
  • 动画时长控制在0.3秒内
  • 交互元素使用弹簧动画
  • 尊重减少动效设置
  • 所有交互都提供视觉反馈

Best Practices

最佳实践

Navigation

导航

  • Hierarchical - Use NavigationStack for drilldown
  • Flat - Use TabView for peer destinations
  • Content-Driven - Use for media apps
  • 层级式 - 使用NavigationStack进行深度导航
  • 扁平式 - 使用TabView切换同级目的地
  • 内容驱动式 - 适用于媒体类应用

Feedback

反馈

  • Visual - Highlight on tap
  • Haptic - Use UIImpactFeedbackGenerator
  • Audio - Use system sounds sparingly
  • 视觉反馈 - 点击时高亮
  • 触觉反馈 - 使用UIImpactFeedbackGenerator
  • 音频反馈 - 谨慎使用系统音效

Loading States

加载状态

swift
struct LoadingView: View {
    var body: some View {
        VStack {
            ProgressView()
                .scaleEffect(1.5)
            Text("Loading...")
                .font(.caption)
                .foregroundColor(.secondary)
                .padding(.top)
        }
    }
}
swift
struct LoadingView: View {
    var body: some View {
        VStack {
            ProgressView()
                .scaleEffect(1.5)
            Text("Loading...")
                .font(.caption)
                .foregroundColor(.secondary)
                .padding(.top)
        }
    }
}

Error States

错误状态

swift
struct ErrorView: View {
    let message: String
    let retry: () -> Void

    var body: some View {
        VStack(spacing: 16) {
            Image(systemName: "exclamationmark.triangle")
                .font(.system(size: 48))
                .foregroundColor(.orange)

            Text("Something went wrong")
                .font(.headline)

            Text(message)
                .font(.subheadline)
                .foregroundColor(.secondary)
                .multilineTextAlignment(.center)

            Button("Try Again") {
                retry()
            }
            .buttonStyle(.borderedProminent)
        }
        .padding()
    }
}
swift
struct ErrorView: View {
    let message: String
    let retry: () -> Void

    var body: some View {
        VStack(spacing: 16) {
            Image(systemName: "exclamationmark.triangle")
                .font(.system(size: 48))
                .foregroundColor(.orange)

            Text("Something went wrong")
                .font(.headline)

            Text(message)
                .font(.subheadline)
                .foregroundColor(.secondary)
                .multilineTextAlignment(.center)

            Button("Try Again") {
                retry()
            }
            .buttonStyle(.borderedProminent)
        }
        .padding()
    }
}

Empty States

空状态

swift
struct EmptyStateView: View {
    var body: some View {
        VStack(spacing: 16) {
            Image(systemName: "tray")
                .font(.system(size: 64))
                .foregroundColor(.secondary)

            Text("No Items")
                .font(.title2)

            Text("Your items will appear here")
                .font(.subheadline)
                .foregroundColor(.secondary)

            Button("Add Item") {
                // Action
            }
            .buttonStyle(.borderedProminent)
        }
    }
}
swift
struct EmptyStateView: View {
    var body: some View {
        VStack(spacing: 16) {
            Image(systemName: "tray")
                .font(.system(size: 64))
                .foregroundColor(.secondary)

            Text("No Items")
                .font(.title2)

            Text("Your items will appear here")
                .font(.subheadline)
                .foregroundColor(.secondary)

            Button("Add Item") {
                // 操作
            }
            .buttonStyle(.borderedProminent)
        }
    }
}

Platform Considerations

平台适配注意事项

iPhone

iPhone

  • Design for various sizes (SE, Pro, Pro Max)
  • Support portrait and landscape
  • Use safe areas for notch/Dynamic Island
  • Consider one-handed use
  • 适配多种尺寸(SE、Pro、Pro Max)
  • 支持竖屏和横屏
  • 为刘海屏/灵动岛预留安全区域
  • 考虑单手操作体验

iPad

iPad

  • Support multitasking (Split View, Slide Over)
  • Use sidebars for navigation
  • Adapt to larger screen (don't just scale)
  • Consider keyboard shortcuts
  • Support external displays
  • 支持多任务(分屏、侧拉)
  • 使用侧边栏进行导航
  • 适配大屏幕(不要只是缩放)
  • 支持键盘快捷键
  • 支持外接显示器

Apple Watch

Apple Watch

  • Glanceable information
  • Large touch targets (>44pt)
  • Minimal interaction required
  • Use Digital Crown for scrolling
  • Support Always-On display
  • 信息一目了然
  • 大点击区域(>44pt)
  • 最少交互操作
  • 使用数码表冠滚动
  • 支持常亮显示

Resources

资源


"Design is not just what it looks like and feels like. Design is how it works." - Steve Jobs

“设计不只是外观和手感,更是功能的实现。”——史蒂夫·乔布斯