Highlight
Apple 展示了如何用位置确认、8 小时临时通知权限、SKOverlay 和 secure app group,把扫码点单这类 App Clip 交易流程从调起延续到完整 App。
核心内容
App Clip 的价值来自现场感。用户在店里扫 NFC 标签或 QR code,想做的通常只有一件事:看菜单、付款、取货。完整 App 里的账户中心、设置页、复杂导航,放进这个场景只会拖慢完成任务的速度。
这场 session 用 Fruta 点果昔流程说明问题。没有优化时,用户扫码进入 App Clip 后,还要处理定位权限、通知权限、付款、注册或登录。每一步都合理,连在一起就变成了摩擦。
Apple 给出的办法是把权限请求移到 App Clip Card 和系统能力里。位置确认只返回物理码是否在指定区域内取得,不暴露完整定位。App Clip notification 可以在每次启动后提供最长 8 小时的临时通知权限。Apple Pay 负责付款,Sign in with Apple 和 secure app group 负责把身份延续到完整 App。
这也是构建方式上的取舍。App Clip 应该只带完成当前任务所需的资源,启动后立即可用。共享资产可以放在共享 asset catalog,共享类和本地化字符串可以在 App 和 App Clip 之间复用。创建账户这类重任务放在交易完成后,或等用户安装完整 App 后再处理。
详细内容
用位置确认保护物理码交易
(07:53)物理码会把用户带到某个 App Clip experience。问题是,码可能贴错门店,也可能被人恶意替换。App Clip 的位置确认 API 让应用验证“这个码是否在预期区域内被取得”,返回结果是一个 yes/no 判断。
import AppClip
guard let payload = userActivity.appClipActivationPayload else {
return
}
let region = CLCircularRegion(center: CLLocationCoordinate2D(latitude: 37.3298193,
longitude: -122.0071671), radius: 100, identifier: "apple_park")
payload.confirmAcquired(in: region) { (inRegion, error) in
}
关键点:
userActivity.appClipActivationPayload来自 App Clip 的调起上下文。CLCircularRegion描述物理码应该出现的位置范围;session 提到半径最大可到 500 米。confirmAcquired(in:)只确认 payload 是否在该区域内取得。inRegion为 false 时,可以阻止付款或提示用户检查门店。
读取 App Clip Card 上的临时通知授权
(09:24)App Clip 可以在 Card 上请求临时通知权限。用户同意后,App Clip 每次启动后最多有 8 小时通知能力,适合订单完成、取货提醒、排队状态这类短生命周期消息。
import UserNotifications
let center = UNUserNotificationCenter.current()
center.getNotificationSettings { (settings) in
if settings.authorizationStatus == .ephemeral {
// User has already granted ephemeral notification.
}
}
关键点:
UNUserNotificationCenter.current()读取当前通知设置。.ephemeral是 App Clip 的临时通知授权状态。- 已经取得临时授权时,应用不需要再弹出普通通知权限请求。
- 对更长期的通知关系,仍然可以在合适时机请求常规通知权限。
在任务完成后展示 SKOverlay
(10:49)用户完成付款后,才是引导安装完整 App 的好时机。StoreKit 的 SKOverlay.AppClipConfiguration 可以把 App Store 入口嵌入 App Clip 视图中,session 建议把它放在付款确认页附近。
import SwiftUI
import StoreKit
struct ContentView : View {
@State private var finishedPaymentFlow = false
var body: some View {
NavigationView {
CheckoutView($finishedPaymentFlow)
}
.appStoreOverlay(isPresented: $finishedPaymentFlow) {
SKOverlay.AppClipConfiguration(position: .bottom)
}
}
}
关键点:
finishedPaymentFlow表示用户是否已经完成付款流程。.appStoreOverlay(isPresented:)把 overlay 的显示时机交给 SwiftUI 状态控制。SKOverlay.AppClipConfiguration(position: .bottom)使用 App Clip 专用配置。- overlay 不打断下单过程,适合在确认页提示用户安装完整 App。
把登录状态迁移到完整 App
(11:32)App Clip 被完整 App 取代时,可以通过 secure app group 传递少量用户数据。session 的做法是在 App Clip 内使用 Sign in with Apple,成功后把 credential.user 保存到共享 group container。
// Automatically log in with Sign in with Apple
import AuthenticationServices
SignInWithAppleButton(.signUp, onRequest: { _ in
}, onCompletion: { result in
switch result {
case .success(let authorization):
guard let secureAppGroupURL =
FileManager.default.containerURL(forSecurityApplicationGroupIdentifier:
"group.com.example.apple-samplecode.fruta")
else { return };
guard let credential = authorization.credential as? ASAuthorizationAppleIDCredential
else { return }
save(userID: credential.user, in: secureAppGroupURL)
case .failure(let error):
print(error)
}
})
关键点:
SignInWithAppleButton在 App Clip 内完成注册或登录。containerURL(forSecurityApplicationGroupIdentifier:)取得 App Clip 和完整 App 可共享的容器。ASAuthorizationAppleIDCredential提供稳定的user标识。- 这里只保存用户标识,完整 App 启动后还要再次验证凭证状态。
(11:55)完整 App 首次启动后,读取同一个 group container 中的用户标识,再用 ASAuthorizationAppleIDProvider 验证凭证仍然有效。验证通过后,应用可以恢复用户的收藏、奖励或订单历史。
import AuthenticationServices
let provider = ASAuthorizationAppleIDProvider()
guard let secureAppGroupURL =
FileManager.default.containerURL(forSecurityApplicationGroupIdentifier:
"group.com.example.apple-samplecode.fruta")
else { return };
let user = readUserID(in: secureAppGroupURL)
provider.getCredentialState(forUserID: user) { state, error in
if state == .authorized {
loadFavoriteSmoothies(userID: user)
}
}
关键点:
- 完整 App 读取的是 App Clip 写入的同一个 secure app group。
ASAuthorizationAppleIDProvider负责检查用户标识的授权状态。state == .authorized后再加载用户相关数据。- 这个流程让用户从 App Clip 安装完整 App 后直接回到已登录状态。
核心启发
1. 为门店二维码加上付款前校验
做什么:在点餐、停车、租借设备等 App Clip 中,付款前确认调起码是否在合法区域内取得。
为什么值得做:session 的 Fruta 示例说明,贴错或被替换的 QR code 会把用户带到错误门店,位置确认可以在不请求完整定位权限的情况下拦截风险。
怎么开始:在 App Clip 的 Info.plist 开启位置确认,解析 activation payload,按门店配置生成 CLCircularRegion,再用 confirmAcquired(in:) 决定是否放行付款。
2. 把短生命周期消息改成 App Clip notification
做什么:为取餐、排队、临时通行、一次性预约发送 8 小时内有效的通知。
为什么值得做:用户只需要知道“果昔好了”或“车位快到期”,普通通知权限会显得过重;临时授权能覆盖这类即时任务。
怎么开始:在 App Clip Card 请求 ephemeral notification,启动后用 getNotificationSettings 检查 .ephemeral,只在需要长期关系时再请求常规通知权限。
3. 把安装完整 App 放到任务完成后
做什么:用户付款成功、领取凭证或完成预约后,用 SKOverlay 提示安装完整 App。
为什么值得做:session 明确建议 overlay 放在用户完成任务后,例如付款确认页旁边。此时用户已经获得价值,更容易接受完整 App。
怎么开始:把交易完成状态绑定到 appStoreOverlay(isPresented:),使用 SKOverlay.AppClipConfiguration(position: .bottom),避免在任务开始前打断流程。
4. 让 App Clip 登录自然迁移到完整 App
做什么:用户在 App Clip 中用 Sign in with Apple 登录后,安装完整 App 时自动恢复身份。
为什么值得做:App Clip 被完整 App 取代时,secure app group 会转移给完整 App。用户不需要再次登录,就能看到奖励、收藏或历史订单。
怎么开始:App Clip 登录成功后把 credential.user 写入 group container;完整 App 启动时读取该值,用 getCredentialState(forUserID:) 验证后再加载账户数据。
关联 Session
- Explore App Clips — App Clips 的入门 session,解释核心任务、触发场景,以及 App Clip 与完整 App 的关系。
- Configure and link your App Clips — 讲解 App Clip Code、NFC、QR code、Universal Links、Associated Domains 和 App Store Connect 配置。
- Design great App Clips — 从设计角度拆解快速、聚焦、低摩擦的 App Clip 流程和下载完整 App 的引导。
- What’s new with in-app purchase — 补充 StoreKit、SKOverlay、App Store server notifications、SKAdNetwork 等购买和转化能力。
- Get the most out of Sign in with Apple — 深入讲解 Sign in with Apple 的授权请求、凭证状态验证和账户迁移。
评论
GitHub Issues · utterances