设计出色的 App Clips
Design great App Clips
2020年6月23日
一句话判断
App Clips 的设计哲学只有八个字:“秒开、秒用、不废话”——如果你设计 App Clip 时还在想”怎么让用户看到更多功能”,你就搞反了。
这场 Session 讲了什么
这场 Session 从设计和用户体验角度讲解了如何打造优秀的 App Clip。App Clip 是主应用的轻量级版本,用户通过 NFC、QR 码或 Safari 横幅触发后,无需安装完整应用即可使用核心功能。Session 强调了 App Clip 设计的三个核心原则:即时性(instant)、轻量化(lightweight)和聚焦性(focused)。
即时性意味着 App Clip 必须在几秒内完成加载并展示核心功能。用户扫码点咖啡的期望是”看到菜单 -> 下单 -> 付款”,而不是”看到欢迎页 -> 注册账号 -> 填写个人信息 -> 然后才能点餐”。Session 反复强调了”零摩擦”的设计目标——利用 Sign in with Apple 的自动静默登录和 Apple Pay 的一键支付,消除所有不必要的交互步骤。
轻量化要求 App Clip 只包含完成当前任务所需的最少功能。Session 展示了几个反面教材:把完整应用的导航栏、设置页、个人中心都塞进 App Clip,导致体积超限、加载缓慢。正确的做法是只保留一条线性任务流,完成任务后通过 SKOverlay 引导用户安装完整应用。
值得深挖的点
任务流设计的”单线原则”
App Clip 应该只有一条线性的任务流:进入 -> 执行核心操作 -> 完成/安装完整应用。不要提供分支选项、不要让用户做选择、不要展示与当前场景无关的功能。Session 用停车场缴费的例子说明——用户扫了停车位的二维码,App Clip 应该直接展示”确认缴费 ¥15,车牌号 xxx”,而不是展示停车场的楼层导航、会员注册和积分商城。
Sign in with Apple 与 Apple Pay 的”免登录”体验
App Clip 可以利用 Sign in with Apple 的静默模式——用户第一次使用时自动创建临时账号,无需任何登录操作。配合 Apple Pay,用户在 App Clip 中的整个流程可以是:扫码 -> 看到订单 -> 指纹确认支付 -> 完成。全程零输入、零注册、零等待。Session 将这种体验称为”像用自助售货机一样简单”。
代码片段
// App Clip 的精简任务流设计
import SwiftUI
struct CoffeeOrderClipView: View {
let storeName: String
let storeID: String
@State private var selectedDrink: Drink?
@State private var isProcessing = false
var body: some View {
// 单一任务流:选饮品 -> 确认 -> 支付
VStack(spacing: 16) {
// 顶部:店铺信息,来自扫码 URL 参数
Text(storeName)
.font(.headline)
.padding(.top)
// 饮品选择(简洁网格)
LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible())],
spacing: 12) {
ForEach(drinks) { drink in
DrinkCard(drink: drink)
.onTapGesture {
selectedDrink = drink
}
}
}
Spacer()
// 底部:一键支付按钮
if let drink = selectedDrink {
PayButton(drink: drink, storeID: storeID) {
isProcessing = true
}
.padding(.bottom)
}
}
// 不显示导航栏,不提供返回上一级
.navigationBarHidden(true)
}
}
// 利用 Apple Pay 实现一键支付
import SwiftUI
import PassKit
struct PayButton: View {
let drink: Drink
let storeID: String
let onPaymentStart: () -> Void
// 检查设备是否支持 Apple Pay
var applePayAvailable: Bool {
PKPaymentAuthorizationController.canMakePayments(
usingNetworks: [.visa, .masterCard, .chinaUnionPay]
)
}
var body: some View {
VStack(spacing: 8) {
Text("\(drink.name) - ¥\(drink.price)")
.font(.subheadline)
if applePayAvailable {
// 使用 Apple Pay 按钮
Button {
onPaymentStart()
initiateApplePay()
} label: {
Text("用 Apple Pay 支付")
.bold()
.frame(maxWidth: .infinity)
.padding()
.background(Color.black)
.foregroundColor(.white)
.cornerRadius(10)
}
}
}
}
func initiateApplePay() {
let request = PKPaymentRequest()
request.merchantIdentifier = "merchant.your.id"
request.paymentSummaryItems = [
PKPaymentSummaryItem(label: drink.name, amount: NSDecimalNumber(value: drink.price))
]
request.supportedNetworks = [.visa, .masterCard, .chinaUnionPay]
request.merchantCapabilities = .capability3DS
// 直接弹出 Apple Pay,不需要任何用户信息填写
let controller = PKPaymentAuthorizationController(paymentRequest: request)
// controller.delegate = self
controller.present()
}
}
// 任务完成后引导安装完整应用
import StoreKit
struct OrderCompleteView: View {
var body: some View {
VStack(spacing: 20) {
Image(systemName: "checkmark.circle.fill")
.font(.system(size: 60))
.foregroundColor(.green)
Text("下单成功!")
.font(.title2)
.fontWeight(.semibold)
Text("正在制作中,预计 5 分钟")
.font(.subheadline)
.foregroundColor(.secondary)
Button("完成") {
// 展示安装完整应用的引导
showAppStoreOverlay()
}
.buttonStyle(.borderedProminent)
}
}
func showAppStoreOverlay() {
let config = SKOverlay.AppClipConfiguration(position: .bottom)
let overlay = SKOverlay(
appIdentifier: "你的AppStoreID",
configuration: config
)
if let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene {
overlay.present(in: scene)
}
}
}
最佳实践
- App Clip 的首屏加载时间控制在 3 秒以内,超过这个时间用户会直接离开
- 利用 URL 参数直接跳转到具体功能,不要展示通用的”首页”
- 使用 Sign in with Apple 的静默模式,避免任何注册/登录步骤
- 在 App Clip 完成任务后,通过 SKOverlay 非侵入式地引导安装完整应用
- 为每个物理触点(NFC 标签、QR 码)设计独立的 App Clip 体验 URL
还有什么值得关注
- App Clip 的 10MB 体积限制意味着你不能使用 On-Demand Resources,但可以引用系统框架的功能
- Session 提到了 App Clip Code——一种 Apple 设计的新二维码,同时支持 NFC 和视觉扫描
- 用户完成 App Clip 体验后,完整应用会在后台自动下载(如果用户同意安装),确保打开完整应用时数据无缝衔接