名称: iOS移动设计 描述: 掌握iOS人机界面指南和SwiftUI模式,用于构建原生iOS应用程序。在设计iOS界面、实现SwiftUI视图或确保应用遵循Apple设计原则时使用。
iOS移动设计
掌握iOS人机界面指南(HIG)和SwiftUI模式,以构建精美、原生的iOS应用程序,使其在Apple平台上感觉自然。
何时使用此技能
- 遵循Apple HIG设计iOS应用界面
- 构建SwiftUI视图和布局
- 实现iOS导航模式(NavigationStack, TabView, sheets)
- 为iPhone和iPad创建自适应布局
- 使用SF符号和系统排版
- 构建可访问的iOS界面
- 实现iOS特定手势和交互
- 为动态类型和深色模式设计
核心概念
1. 人机界面指南原则
清晰度: 内容可读,图标精确,装饰微妙 遵从性: UI帮助用户理解内容而不与其竞争 深度: 视觉层和运动传达层次结构并支持导航
平台考虑:
- iOS: 以触摸为先,紧凑显示屏,纵向方向
- iPadOS: 更大画布,多任务处理,指针支持
- visionOS: 空间计算,眼/手输入
2. SwiftUI布局系统
基于堆栈的布局:
// 垂直堆栈对齐
VStack(alignment: .leading, spacing: 12) {
Text("标题")
.font(.headline)
Text("副标题")
.font(.subheadline)
.foregroundStyle(.secondary)
}
// 水平堆栈灵活间距
HStack {
Image(systemName: "star.fill")
Text("特色")
Spacer()
Text("查看全部")
.foregroundStyle(.blue)
}
网格布局:
// 自适应网格填充可用宽度
LazyVGrid(columns: [
GridItem(.adaptive(minimum: 150, maximum: 200))
], spacing: 16) {
ForEach(items) { item in
ItemCard(item: item)
}
}
// 固定列网格
LazyVGrid(columns: [
GridItem(.flexible()),
GridItem(.flexible()),
GridItem(.flexible())
], spacing: 12) {
ForEach(items) { item in
ItemThumbnail(item: item)
}
}
3. 导航模式
NavigationStack (iOS 16+):
struct ContentView: View {
@State private var path = NavigationPath()
var body: some View {
NavigationStack(path: $path) {
List(items) { item in
NavigationLink(value: item) {
ItemRow(item: item)
}
}
.navigationTitle("项目")
.navigationDestination(for: Item.self) { item in
ItemDetailView(item: item)
}
}
}
}
TabView:
struct MainTabView: View {
@State private var selectedTab = 0
var body: some View {
TabView(selection: $selectedTab) {
HomeView()
.tabItem {
Label("主页", systemImage: "house")
}
.tag(0)
SearchView()
.tabItem {
Label("搜索", systemImage: "magnifyingglass")
}
.tag(1)
ProfileView()
.tabItem {
Label("个人资料", systemImage: "person")
}
.tag(2)
}
}
}
4. 系统集成
SF符号:
// 基本符号
Image(systemName: "heart.fill")
.foregroundStyle(.red)
// 带有渲染模式的符号
Image(systemName: "cloud.sun.fill")
.symbolRenderingMode(.multicolor)
// 可变符号 (iOS 16+)
Image(systemName: "speaker.wave.3.fill", variableValue: volume)
// 符号效果 (iOS 17+)
Image(systemName: "bell.fill")
.symbolEffect(.bounce, value: notificationCount)
动态类型:
// 使用语义字体
Text("标题")
.font(.headline)
Text("随用户偏好缩放的主体文本")
.font(.body)
// 尊重动态类型的自定义字体
Text("自定义")
.font(.custom("Avenir", size: 17, relativeTo: .body))
5. 视觉设计
颜色和材质:
// 语义颜色适应亮/深色模式
Text("主要")
.foregroundStyle(.primary)
Text("次要")
.foregroundStyle(.secondary)
// 用于模糊效果的系统材质
Rectangle()
.fill(.ultraThinMaterial)
.frame(height: 100)
// 用于叠加的鲜明材质
Text("叠加")
.padding()
.background(.regularMaterial, in: RoundedRectangle(cornerRadius: 12))
阴影和深度:
// 标准卡片阴影
RoundedRectangle(cornerRadius: 16)
.fill(.background)
.shadow(color: .black.opacity(0.1), radius: 8, y: 4)
// 提升外观
.shadow(radius: 2, y: 1)
.shadow(radius: 8, y: 4)
快速启动组件
import SwiftUI
struct FeatureCard: View {
let title: String
let description: String
let systemImage: String
var body: some View {
HStack(spacing: 16) {
Image(systemName: systemImage)
.font(.title)
.foregroundStyle(.blue)
.frame(width: 44, height: 44)
.background(.blue.opacity(0.1), in: Circle())
VStack(alignment: .leading, spacing: 4) {
Text(title)
.font(.headline)
Text(description)
.font(.subheadline)
.foregroundStyle(.secondary)
.lineLimit(2)
}
Spacer()
Image(systemName: "chevron.right")
.foregroundStyle(.tertiary)
}
.padding()
.background(.background, in: RoundedRectangle(cornerRadius: 12))
.shadow(color: .black.opacity(0.05), radius: 4, y: 2)
}
}
最佳实践
- 使用语义颜色: 始终使用
.primary、.secondary、.background以支持自动亮/深色模式 - 拥抱SF符号: 使用系统符号以确保一致性和自动可访问性
- 支持动态类型: 使用语义字体(
.body、.headline)而非固定大小 - 添加可访问性: 包括
.accessibilityLabel()和.accessibilityHint()修饰符 - 使用安全区域: 尊重
safeAreaInset并避免在屏幕边缘硬编码填充 - 实现状态恢复: 使用
@SceneStorage以保存用户状态 - 支持iPad多任务处理: 设计用于分屏视图和滑动覆盖
- 在设备上测试: 模拟器不捕捉完整触觉和性能体验
常见问题
- 布局断裂: 谨慎使用
.fixedSize();首选灵活布局 - 性能问题: 对长滚动列表使用
LazyVStack/LazyHStack - 导航错误: 确保
NavigationLink值是Hashable的 - 深色模式问题: 避免硬编码颜色;使用语义或资产目录颜色
- 可访问性失败: 启用VoiceOver进行测试
- 内存泄漏: 注意闭包中的强引用循环