WWDC Quick Look 💓 By SwiftGGTeam
Principles of great design

Principles of great design

观看原视频

Highlight

Apple 将设计定义为”带着意图去创造”,并围绕 Purpose、Agency、Responsibility、Familiarity、Flexibility、Simplicity、Craft、Delight 八大原则,为开发者提供了一套在 AI 时代尤其需要遵守的设计准则:每个 Feature 都在消耗用户的时间、注意力和信任,决定”不做什么”比”做什么”更重要。

核心内容

Purpose:先想清楚,再动手

00:32

很多团队接到需求后,第一反应是画原型、写代码。Apple 在这次 Session 开头就泼了冷水:在画第一根线、写第一行代码之前,先问自己——这东西有没有 Purpose(目的)?

每个你加进产品的 Feature,都在向用户索取时间、注意力和信任。这三样东西很贵,浪费不起。所以”决定不做什么”往往比”做什么”更考验判断力。一个功能如果存在,就必须有清晰的价值主张,而不是”别人有,所以我也得有”。

Agency:把控制权交给用户

01:52

Agency(用户控制权)的核心是让用户按自己的方式做事。界面不该挡在用户和目标之间,不该把用户引向一条预设好的单行道。

但给了自由,用户就会犯错。这时候需要 Forgiveness(宽容度)来兜底。用户误删了文件、发错了消息,你要让 Undo(撤销)变得容易。只有在真正不可逆的破坏性操作前,才用阻断式确认弹窗。这种设计让用户敢于探索,因为他们知道系统会帮自己兜底。

Responsibility:隐私和安全是底线

03:38

Responsibility(责任)从隐私开始。Apple 的立场很明确:不要在 App 启动瞬间就抛出权限请求。用户还没搞清楚这个 App 是干什么的,就被要求交出位置、相册、通讯录。这就像陌生人上来就要你手机号,你会信任他吗?

负责任的界面会在正确的时机请求数据,只请求必要的数据,并透明说明用途。

更值得关注的是 AI 场景下的责任。(05:10)Apple 举了一个食谱 App 的例子:如果用户标注了花生过敏,AI 却推荐了含花生的菜谱,这会造成真实的身体伤害。Apple 的态度是——预判最坏情况,加安全护栏。如果风险大于价值,直接砍掉这个功能,而不是甩给用户一句”AI 可能不准确”的免责声明。

Familiarity:利用用户已有的认知

06:02

Familiarity(熟悉感)用利代替让你照搬别人的设计,用用户已经知道的东西。隐喻(Metaphor)从最早的图形界面就开始用了:垃圾桶表示删除,因为用户知道现实中的垃圾桶是放不要的东西的。

好的隐喻不能太具象(用户可能没见过),也不能太抽象(用户猜不到功能)。一致性也很关键:长得一样的控件,行为必须一样;常用操作的位置,跨屏跨设备要固定。Mac 的关闭按钮永远在左上角,用户不用想就知道去哪点。

Flexibility:适配不同的使用场景

08:54

同一个人听音乐的交互方式,在家、跑步、开车时完全不同。灵活的界面要适配这些真实场景:iPhone 上适合快速触控,Mac 上适合深度工作流,CarPlay 上需要完全免手操作。

灵活性还体现在包容性上。用户的年龄、语言、能力各不相同。你不需要第一天就覆盖所有人,但要开始思考如何让体验更具包容性。比如允许用户自定义控件布局,隐藏不常用的按钮。

Simplicity:去掉不必要的,让核心目的发光

11:13

Apple 特意区分了 Simplicity(简洁)和 Minimalism(极简)。把功能全塞进一个菜单,界面看起来干净了,用起来却更复杂。真正的简洁是消除摩擦:用户能毫不费力地找到需要的东西。

简洁通过 Concise(精炼)和 Clear(清晰)来实现。精炼的界面用平实语言,去掉行话,减少操作步骤。清晰的界面用层级(Hierarchy)引导注意力——通过顺序、间距和对比,让屏幕上最重要的东西一眼就能看到。

有时候,简洁反而意味着增加内容。(13:06)一个简单的播放/暂停按钮,在暂停一段时间后再回来,用户需要更多上下文:播到哪了?还剩多久?增加这些信息,让用户做出知情决策,这才是简洁。

Craft:细节决定信任

13:42

Craft(工艺)是用户能感受到的用心程度。按钮点了没反应、滚动卡顿、图标没对齐、旋转屏幕布局错乱——这些细节会让用户怀疑整个产品的质量。

高质量的 Craft 包括:跨设备都好看的字体、自适应明暗模式的配色、清晰的图标、流畅的动画反馈。这些用建代替锦上添花,立信任的基础。Craft 来自反复迭代,而且是一个持续的过程。平台更新、新硬件出现时,要主动评估是否对自己的体验有价值。

Delight:愉悦是所有原则做对之后的自然结果

15:48

Delight(愉悦感)很难定义,但体验到了就知道。Apple 的提醒很直接:不要靠撒彩纸、加特效来制造愉悦。真正的愉悦来自确定你想让用户感受到什么情绪——放松、自信、兴奋——然后在设计中持续强化这种情绪。Delight 是所有原则都做到位之后的自然产物。

详细内容

用 Undo 机制替代阻断式确认弹窗

Agency 原则中,Forgiveness 的具体实现就是强大的 Undo 支持。下面是一个 SwiftUI 中结合 UndoManager 和底部提示的实现:

struct TaskListView: View {
    @State private var tasks = ["写周报", "Review 代码", "更新文档"]
    @Environment(\.undoManager) private var undoManager
    @State private var showUndoToast = false
    @State private var deletedTask: String?
    @State private var deletedIndex: Int?

    var body: some View {
        List {
            ForEach(tasks, id: \.self) { task in
                Text(task)
            }
            .onDelete { indexSet in
                let index = indexSet.first!
                deletedTask = tasks[index]
                deletedIndex = index
                tasks.remove(at: index)

                undoManager?.registerUndo(withTarget: self) { target in
                    if let task = target.deletedTask,
                       let idx = target.deletedIndex {
                        target.tasks.insert(task, at: idx)
                    }
                }
                undoManager?.setActionName("删除任务")
                showUndoToast = true

                DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
                    showUndoToast = false
                }
            }
        }
        .overlay(alignment: .bottom) {
            if showUndoToast {
                HStack(spacing: 12) {
                    Text("已删除")
                    Button("撤销") {
                        undoManager?.undo()
                        showUndoToast = false
                    }
                    .fontWeight(.semibold)
                }
                .padding(.horizontal, 16)
                .padding(.vertical, 10)
                .background(.ultraThinMaterial, in: Capsule())
                .padding(.bottom, 40)
            }
        }
    }
}

关键点:

  • @Environment(\.undoManager) 获取系统提供的撤销管理器,支持 Shake to Undo 等系统级手势
  • registerUndo(withTarget:) 注册逆向操作,将删除的数据插回原位置
  • setActionName(_:) 设置撤销操作的显示名称,在系统撤销菜单中可见
  • 底部非阻断式提示替代 Alert,用户可以继续操作,3 秒后自动消失
  • 只在真正不可逆的操作(如清空数据库、注销账号)才使用阻断式确认

负责任的权限请求:Just-in-time 策略

Responsibility 原则要求权限请求在正确的时机发生。SwiftUI 的 PhotosPicker 天然遵循这个原则:

struct ProfileSetupView: View {
    @State private var selectedItems: [PhotosPickerItem] = []
    @State private var showPicker = false

    var body: some View {
        VStack(spacing: 20) {
            Text("设置头像")
                .font(.title2)

            Button("从相册选择") {
                showPicker = true
            }
            .buttonStyle(.borderedProminent)
        }
        .photosPicker(
            isPresented: $showPicker,
            selection: $selectedItems,
            matching: .images
        )
        .onChange(of: selectedItems) { _, newItems in
            guard let item = newItems.first else { return }
            loadImage(from: item)
        }
    }

    private func loadImage(from item: PhotosPickerItem) {
        item.loadTransferable(type: Data.self) { result in
            // 处理选中的图片数据
        }
    }
}

关键点:

  • 权限弹窗只在用户点击”从相册选择”时触发,不是 App 启动时
  • PhotosPicker 默认请求 Limited Access(仅选中的照片),符合最小权限原则
  • 避免使用旧的 UIImagePickerController 请求 Full Access,审核风险高
  • 用户选择完成后通过 loadTransferable 异步加载数据,不阻塞主线程

用触觉反馈强化 Craft

Craft 原则要求界面有精细的反馈。SwiftUI 的 sensoryFeedback 让触觉反馈变得声明式:

struct CheckInButton: View {
    @State private var isCheckedIn = false

    var body: some View {
        Button {
            isCheckedIn.toggle()
        } label: {
            Image(systemName: isCheckedIn ? "checkmark.circle.fill" : "circle")
                .font(.system(size: 56))
                .foregroundStyle(isCheckedIn ? .green : .gray)
                .contentTransition(.symbolEffect(.replace))
        }
        .sensoryFeedback(.success, trigger: isCheckedIn) { oldValue, newValue in
            newValue == true
        }
        .sensoryFeedback(.impact, trigger: isCheckedIn) { oldValue, newValue in
            newValue == false
        }
    }
}

关键点:

  • .sensoryFeedback(_:trigger:condition:) 在 iOS 17+ 可用,条件闭包控制何时触发
  • 打卡成功用 .success 反馈,取消打卡用 .impact 反馈,状态变化有明确区分
  • 不要在 body 里直接调用 UIImpactFeedbackGenerator,会破坏声明式结构
  • 配合 .contentTransition(.symbolEffect(.replace)) 实现图标切换动画,视觉和触觉同步

核心启发

做什么:在 AI 功能中加入”最坏情况”检查清单 为什么值得做:Session 明确要求开发者预判 AI 输出的风险。一个食谱 App 的 AI 推荐错误食材可能危及生命安全,这不是体验问题,是责任问题。 怎么开始:为每个 AI 功能列出三个问题——这个功能被滥用会怎样?谁会受到伤害?怎么预防?如果风险不可控,加二次确认或人工审核;如果风险大于价值,直接移除。

做什么:把 App 里所有的启动时权限请求移到业务触发点 为什么值得做:Responsibility 原则强调”在正确的时机请求”。启动就弹权限是用户流失的重要原因。 怎么开始:扫描 AppDelegateApp 初始化代码和所有 requestAuthorization 调用,把权限请求移到用户主动触发对应功能的代码路径上。用 PhotosPicker 替代手动请求相册权限,用 CoreLocationrequestWhenInUseAuthorization 只在进入地图相关页面时调用。

做什么:用 Undo 替代 80% 的确认弹窗 为什么值得做:Agency 原则的核心是让用户敢于探索。每次弹 Alert 问”确定删除吗”都在消耗用户的耐心和信任。 怎么开始:检查项目中所有 UIAlertControllerconfirmationDialog 的使用场景。对于可恢复的操作(删除列表项、移除标签、取消收藏),改用 UndoManager + 底部提示。只在真正不可逆的操作(清空数据库、注销账号、转账)保留确认弹窗。

做什么:为关键操作增加触觉反馈 为什么值得做:Craft 原则要求”流畅的动画提供即时、自然的反馈”。触觉是建立”实体感”最直接的方式。 怎么开始:在提交表单、完成打卡、发送消息、切换开关等关键交互上,添加 .sensoryFeedback(.success, trigger: state)。注意区分成功和失败的反馈类型(.success vs .error),让用户通过触觉就能感知操作结果。

做什么:做一次”一致性审计” 为什么值得做:Familiarity 原则指出”长得一样的东西行为必须一样”。不一致的界面让用户困惑,增加学习成本。 怎么开始:列出 App 中所有按钮、卡片、列表项的交互行为,检查相同视觉样式的控件是否有一致的行为模式。比如所有带删除线的按钮都是删除操作,所有右上角的三点菜单都是更多选项。把不一致的地方统一。

关联 Session

  • Principles of great design — 品牌识别与视觉系统的设计原则,与本 Session 的设计哲学一脉相承
  • SwiftUI essentials — SwiftUI 新特性,为实践 Session 250 中的 Agency、Simplicity 原则提供技术支撑
  • UIKit modernization — UIKit 现代化改进,帮助开发者在既有代码库中落实 Craft 和 Familiarity 原则
  • Accessibility Reading — 辅助功能阅读体验,对应本 Session 中 Flexibility 原则的包容性设计
  • Agentic apps — AI Agent 应用设计,需要特别关注本 Session 中 Responsibility 原则对 AI 功能的安全要求

评论

GitHub Issues · utterances