Highlight
Apple Location Technologies 团队的 Jon Schoenberg 介绍了 Nearby Interaction 框架在 iOS 16 中的两大新功能:ARKit 增强模式和后台会话。
核心内容
Nearby Interaction 原来解决的是“附近设备在哪里”。它依赖 U1 芯片和 Ultra Wideband(超宽带)测距,让两台设备或一台设备与配件之间获得距离和方向。2020 年支持两台 iPhone,2021 年扩展到 Apple Watch 和第三方 UWB 配件。
这个模型适合用户拿着手机主动寻找目标。问题出在两个地方。第一,UWB 的方向信息有视场角和遮挡限制,用户可能转到某个角度后拿不到稳定方向。第二,App 进入后台或锁屏后,正在运行的 NISession 会暂停,配件无法继续完成无感交互。
iOS 16 的更新围绕这两个问题展开。Camera assistance 把 ARKit 计算出的设备轨迹交给 Nearby Interaction,用来扩大有效视场并生成更稳定的方向信息。Accessory background sessions 则允许和 Bluetooth LE 配对的 UWB 配件在 App 后台继续运行 Nearby Interaction 会话。
Session 里的博物馆示例很具体:用户选择下一件展品后,App 发现展品旁边的 UWB 配件,提示用户左右扫动手机,然后显示箭头、判断目标是否在身后,并把 AR 内容叠到展品位置上。这个体验以前要自己协调 UWB、ARKit、蓝牙和前后台状态。现在 Nearby Interaction 把关键路径收进框架里。
详细内容
开启 ARKit 增强模式
(04:47)如果 App 已经有一个接收 NIDiscoveryToken、创建配置、运行 NISession 的流程,开启 ARKit 增强模式只需要在 NIConfiguration 的子类上设置 isCameraAssistanceEnabled。这个能力同时支持 Apple 设备之间,以及 Apple 设备和第三方 UWB 配件之间的交互。
// 示意代码:session 没有提供完整代码片段,以下只展示 transcript 点名的 API 流程。
let configuration = /* App 既有流程:用 NIDiscoveryToken 创建 NIConfiguration 子类 */
configuration.isCameraAssistanceEnabled = true
let session = NISession()
session.delegate = self
session.run(configuration)
关键点:
NIDiscoveryToken来自 nearby peer,App 用它创建NIConfiguration的子类。isCameraAssistanceEnabled是 iOS 16 新增属性,设置为true后启用 camera assistance。NISession仍然是 Nearby Interaction 的会话入口。run(configuration)启动会话;camera assistance 会让框架自动创建并运行一个内部ARSession。
(05:27)框架自动创建的 ARSession 运行在 App 进程里,所以 App 必须在 Info.plist 里提供相机使用说明。这个说明要告诉用户为什么寻找附近物体需要相机。
<!-- Info.plist:示意配置,文案应按 App 场景改写。 -->
<key>NSCameraUsageDescription</key>
<string>使用相机来提高附近物体方向判断并显示空间指引。</string>
关键点:
NSCameraUsageDescription是系统相机权限说明键。- camera assistance 会用到 ARKit,因此会触发相机权限要求。
- 文案要解释“寻找附近物体”和“相机”之间的关系,避免用户看到权限弹窗时困惑。
和现有 ARKit 体验共享 ARSession
(06:19)一个 App 同一时间只能运行一个 ARSession。如果 App 已经有 ARKit 体验,不能再让 Nearby Interaction 自动创建第二个会话。做法是在 NISession.run 之前调用新的 setARSession,把 App 自己创建的 ARSession 交给 Nearby Interaction。
// 示意代码:SwiftUI/ARView 场景下共享底层 ARSession。
let niSession = NISession()
let arSession = arView.session
niSession.setARSession(arSession)
niSession.run(configuration)
关键点:
arView.session代表 App 现有 ARKit 视图里的底层ARSession。setARSession必须在NISession.run之前调用。- 调用后,Nearby Interaction 不会再自动创建内部
ARSession。 - 这样 ARKit 画面和 Nearby Interaction 的 camera assistance 可以并行使用同一个轨迹数据来源。
(07:16)直接管理 ARSession 时,Apple 要求用 ARWorldTrackingConfiguration 运行,并按指定方式设置配置:worldAlignment 为 gravity,关闭 collaboration 和 user face tracking,initialWorldMap 为 nil,delegate 的 sessionShouldAttemptRelocalization 返回 false。
// 示意代码:只列出 transcript 明确要求的配置项。
let arConfiguration = ARWorldTrackingConfiguration()
arConfiguration.worldAlignment = .gravity
arConfiguration.isCollaborationEnabled = false
arConfiguration.userFaceTrackingEnabled = false
arConfiguration.initialWorldMap = nil
arSession.run(arConfiguration)
关键点:
ARWorldTrackingConfiguration是共享 ARSession 时的运行配置。.gravity让世界坐标按重力方向对齐。- collaboration 和 user face tracking 必须关闭。
initialWorldMap必须为nil。- 如果配置不符合要求,
NISessionDelegate的didInvalidateWith会收到新的NIError.invalidARConfiguration。
使用新的空间输出属性
(08:21)App 继续通过 NISessionDelegate 的 didUpdateNearbyObjects 接收 nearby object 更新。开启 camera assistance 后,NINearbyObject 新增两个属性:horizontalAngle 和 verticalDirectionEstimate。它们和原来的 distance、direction 一起描述设备到附近物体的空间关系。
// 示意代码:处理 transcript 提到的可选空间属性。
func session(_ session: NISession, didUpdate nearbyObjects: [NINearbyObject]) {
guard let object = nearbyObjects.first else { return }
// distance 可用于显示米级距离。
let distance = object.distance
// direction 可用于 3D 指向;不可用时,可退回到 horizontalAngle。
let direction = object.direction
let horizontalAngle = object.horizontalAngle
// verticalDirectionEstimate 使用前要排除 unknown。
let vertical = object.verticalDirectionEstimate
}
关键点:
distance以米为单位,transcript 将它定义为用户设备和附近物体之间的关键空间关系之一。direction是从当前设备指向附近物体的 3D vector,可能为nil。horizontalAngle是水平方向上的 1D 弧度角;当 3D direction 不能解析时,它仍可能可用。verticalDirectionEstimate是定性垂直关系,可能是 same、above、below、aboveOrBelow 或 unknown。- 使用
verticalDirectionEstimate前要检查 unknown,避免把不确定状态显示成楼层指引。
把附近物体放进 AR 世界
(11:39)iOS 16 在 NISession 上增加了 worldTransform helper。它返回 ARKit 坐标空间里的 transform,用来表示某个 nearby object 在物理环境中的位置。Session 演示里浮在展品位置上的球体,就是用它放进 AR 场景的。
// 示意代码:使用 worldTransform 放置 AR 内容。
if let transform = niSession.worldTransform(for: nearbyObject) {
// 将 AR 标记放到 transform 对应的位置。
} else {
// 提示用户在水平和垂直方向扫动设备。
}
关键点:
worldTransform是NISession上的新 helper method。- 返回值位于 ARKit 的 coordinate space。
- 当 transform 不可用时返回
nil。 - 用户需要在水平和垂直方向充分扫动设备,camera assistance 才能收敛到可用 transform。
- transform 对体验重要时,session 建议提示用户采取动作。
用算法收敛状态指导用户
(13:11)为了让 App 解释为什么 horizontalAngle、verticalDirectionEstimate 或 worldTransform 暂时不可用,NISessionDelegate 新增 didUpdateAlgorithmConvergence。它会返回 NIAlgorithmConvergence 和一个可选的 NINearbyObject。只有开启 camera assistance 时,这个 delegate 才会调用。
// 示意代码:根据收敛状态给用户提示。
func session(_ session: NISession,
didUpdateAlgorithmConvergence convergence: NIAlgorithmConvergence,
for nearbyObject: NINearbyObject?) {
switch convergence.status {
case .converged:
showReadyState()
case .unknown:
showPreparingState()
case .notConverged(let reasons):
showGuidance(for: reasons)
}
}
关键点:
NIAlgorithmConvergence有一个status属性。status是NIAlgorithmConvergenceStatus,表达算法是否已经 converged。nearbyObject为nil时,收敛状态属于整个 session;不为nil时才对应具体物体。notConverged带有 reasons 数组,App 可以按原因给出动作提示。- reason 可能包括总运动不足、水平扫动不足、垂直扫动不足、光照不足。
- 多个 reason 可以同时存在,session 建议按 App 需要顺序引导用户。
按设备能力裁剪体验
(16:23)原来的 NISession.isSupported 只回答设备是否支持 Nearby Interaction。iOS 16 新增 NISession.deviceCapabilities,返回 NIDeviceCapability,让 App 分别检查精确测距、方向测量和 camera assistance。
// 示意代码:按能力选择 UI。
let capabilities = NISession.deviceCapabilities
guard capabilities.supportsPreciseDistanceMeasurement else {
showUnsupportedState()
return
}
if capabilities.supportsCameraAssistance {
enableARGuidanceMode()
} else if capabilities.supportsDirectionMeasurement {
enableDirectionOnlyMode()
} else {
enableDistanceOnlyMode()
}
关键点:
NISession.deviceCapabilities取代只看isSupported的做法。supportsPreciseDistanceMeasurement至少等价于旧的支持性检查。supportsDirectionMeasurement表示设备是否能给出方向测量。supportsCameraAssistance表示设备是否支持 ARKit 增强模式。- session 特别提醒要保留 distance-only 体验,以支持 Apple Watch。
在后台运行配件会话
(18:03)以前 App 进入后台或用户锁屏后,运行中的 NISession 会暂停。iOS 16 的 accessory background sessions 允许 App 利用 Core Bluetooth 后台能力,和已配对的 Bluetooth LE UWB 配件启动并延续 Nearby Interaction 会话。
概念流程:
1. 从配件收到 Ultra Wideband configuration data。
2. 从已配对的 Bluetooth LE 连接中取得该配件的 Bluetooth peer identifier。
3. 用这两份数据创建 NINearbyAccessoryConfiguration。
4. 用这个配置运行 NISession。
关键点:
- Ultra Wideband configuration data 是配件通过数据通道发送给 App 的配置数据。
- Bluetooth peer identifier 来自已配对的 Bluetooth LE 配件。
- transcript 只说明新的 initializer 会接收这两份数据:UWB configuration data 和 Bluetooth peer identifier;没有给出 Swift 参数标签。
- 配件必须已经通过 Bluetooth LE paired。
- 配件还必须实现新的 Nearby Interaction GATT service,让 iOS 验证 Bluetooth identifier 和 UWB configuration 之间的关联。
(22:15)Nearby Interaction GATT service 里有一个加密 characteristic:Accessory Configuration Data。它包含同一份 UWB configuration data。App 不能直接读取这个 characteristic;iOS 用它验证配件的蓝牙身份和 Nearby Interaction 会话是否匹配。
// 示意代码:后台会话需要的 App 配置项。
// Info.plist UIBackgroundModes:
// - nearby-interaction
// - bluetooth-central
关键点:
nearby-interaction对应 session 里提到的 Nearby Interaction background mode。bluetooth-central对应 Xcode 能力里的 “Uses Bluetooth LE accessories”。- App 要能在后台连接配件,因此还要实现 Core Bluetooth 的后台连接和状态恢复流程。
- 触发 LE pairing 会显示用户确认弹窗,session 建议放在 setup flow 或用户明确要交互的时刻。
(25:35)后台会话有一个关键限制:App 在后台不会收到 didUpdateNearbyObjects callback,也不会获得运行时间。NISession 会继续运行,UWB measurements 会到达配件。因此,后台动作必须在配件端根据测量结果执行。
// 示意流程:后台期间由配件消费 UWB measurements。
// App: 建立后台 NISession,并把 sharable configuration 发给配件。
// Accessory: 接收 UWB measurements。
// Accessory: 根据距离或方向触发动作,例如开灯、播放音乐或解锁 eBike。
// App: 只在重要交互时由配件唤起,例如展示通知。
关键点:
- App 后台期间,
NISession不会暂停。 - App 后台期间,
didUpdateNearbyObjects不会回调到 App。 - 配件端会收到 UWB measurements,并应直接决定用户动作。
- 为了省电,session 建议只在重要用户交互时从配件向 App 发送数据。
核心启发
-
做什么:博物馆或展厅的展品导航。 为什么值得做: camera assistance 能让距离、方向、水平角和垂直关系更稳定,适合引导用户走向静止物体。 怎么开始: 给每个展品放置 UWB 配件,在 App 中开启
isCameraAssistanceEnabled,用horizontalAngle画箭头,用worldTransform放置 AR 标记。 -
做什么:多楼层寻物 App。 为什么值得做:
verticalDirectionEstimate提供 same、above、below、aboveOrBelow 这类楼层级提示,比只显示距离更适合室内寻找。 怎么开始: 在didUpdateNearbyObjects中同时读取distance和verticalDirectionEstimate,先提示楼层关系,再显示水平导航。 -
做什么:智能音箱的入屋自动播放。 为什么值得做: accessory background sessions 允许 UWB 配件在 App 后台继续收到测量结果,适合 hands-free 场景。 怎么开始: 让音箱通过 Bluetooth LE paired,实现 Nearby Interaction GATT service,用新的
NINearbyAccessoryConfigurationinitializer 绑定 UWB 数据和CBPeripheral.identifier,在配件端处理测量结果。 -
做什么:电动自行车靠近解锁。 为什么值得做: 用户不必打开 App;配件可以在后台会话中根据 UWB measurements 判断用户是否真正靠近。 怎么开始: App 负责配对、后台连接和会话配置;自行车端根据测量结果执行解锁,并只在需要提示用户时通知 App。
-
做什么:能力自适应的空间交互 UI。 为什么值得做: 不是所有设备都支持方向测量或 camera assistance,Apple Watch 还需要 distance-only 体验。 怎么开始: 启动前读取
NISession.deviceCapabilities,按supportsCameraAssistance、supportsDirectionMeasurement、supportsPreciseDistanceMeasurement分别选择 AR 指引、方向指引或纯距离模式。
关联 Session
- Meet Nearby Interaction — Nearby Interaction 的基础会话模型、距离和方向更新。
- Explore Nearby Interaction with third-party accessories — 第三方 UWB 配件接入 Nearby Interaction 的前置知识。
- Design for spatial interaction — 设计空间感知体验时如何让用户理解设备之间的位置关系。
- Get timely alerts from Bluetooth devices on watchOS — Core Bluetooth 后台发现和配件通知的相关实践。
评论
GitHub Issues · utterances