探索 Nearby Interaction 与第三方配件
Explore Nearby Interaction with third-party accessories
2021年6月8日
一句话判断
Nearby Interaction 框架支持第三方 UWB(Ultra Wideband)配件意味着你的 App 可以精确知道”钥匙在哪里、钱包在哪里、宠物在哪里”——精度达到厘米级,这比 BLE 的”大概在 3 米内”强了一个维度。
这场 Session 讲了什么
Session 介绍了 Nearby Interaction 框架在 iOS 15 中的重大更新:支持与第三方 UWB 配件交互。之前 Nearby Interaction 只能在 Apple 设备之间工作(iPhone 与 Apple Watch、AirTag 之间的 U1 芯片通信)。现在,任何集成了兼容 UWB 芯片的第三方配件都可以通过 Nearby Interaction 框架与 iPhone 通信。
技术实现基于 Apple 定义的超宽带协议栈。第三方配件厂商需要按照 Apple 的 MFi(Made for iPhone)规范实现 UWB 通信协议。App 端使用 NISession 创建交互会话,通过 NINearbyAccessoryConfiguration 配置目标配件的标识符,然后持续接收距离和方向(angle)更新。Session 还介绍了 Camera Assistance 模式——当用户通过 AR 界面寻找配件时,结合相机画面在屏幕上显示实时的距离和方向指引。
值得深挖的点
距离和方向的精度表现
UWB 的测距精度可以达到 +/-10 厘米以内,方向精度在 1-2 米距离内约为 +/-5 度。但精度受环境影响很大:金属表面、厚墙壁、人体遮挡都会降低精度。Session 建议在做距离显示时做平滑处理(moving average),避免原始数据的抖动让用户困惑。方向数据在某些角度存在”模糊区”(ambiguity zone),需要结合多次测量才能确定准确方向。
Accessory Configuration 的安全模型
第三方配件不能随意和任何 iPhone 通信。每个配件都有一个唯一的 token,App 需要通过 NINearbyAccessoryConfiguration(token:config:) 提供这个 token 来建立会话。token 通过你的服务器和配件厂商的服务器协商获取。这个设计保证了只有经过授权的 App 才能追踪特定的配件——防止被陌生人追踪的安全隐患。
代码片段
// 创建与第三方 UWB 配件的 Nearby Interaction 会话
class AccessoryTracker: NSObject, NISessionDelegate {
private var session: NISession?
func startTracking(accessoryToken: Data) {
// 创建交互会话
session = NISession()
session?.delegate = self
// 使用配件的 token 配置追踪目标
let config = NINearbyAccessoryConfiguration(
bluetoothIdentifier: nil,
accessoryType: .physical,
accessoryToken: accessoryToken
)
session?.run(config)
}
// 接收距离和方向更新
func session(_ session: NISession,
didUpdate nearbyObjects: [NINearbyObject]) {
guard let accessory = nearbyObjects.first else { return }
if let distance = accessory.distance {
print("距离配件: \(String(format: "%.2f", distance)) 米")
}
if let direction = accessory.direction {
// direction 是一个 SIMD3<Float>,表示从手机到配件的方向向量
print("方向: \(direction)")
}
}
}
// 结合 AR 界面显示配件位置指引
class AccessoryARView: ARView, NISessionDelegate {
private var distanceLabel: UILabel!
private var directionArrow: UIView!
func session(_ session: NISession,
didUpdate nearbyObjects: [NINearbyObject]) {
guard let accessory = nearbyObjects.first,
let distance = accessory.distance else { return }
// 更新距离显示
DispatchQueue.main.async {
if distance < 0.5 {
self.distanceLabel.text = "就在附近!"
self.distanceLabel.textColor = .green
} else {
self.distanceLabel.text = String(format: "%.1f 米", distance)
self.distanceLabel.textColor = .white
}
// 根据方向更新箭头指向
if let direction = accessory.direction {
self.updateArrowDirection(direction)
}
}
}
private func updateArrowDirection(_ direction: simd_float3) {
// 计算水平角度,旋转箭头 UI
let angle = atan2(direction.x, direction.z)
directionArrow.transform = CGAffineTransform(rotationAngle: CGFloat(angle))
}
}
// 处理会话中断和恢复
func sessionWasSuspended(_ session: NISession) {
print("UWB 会话被挂起(App 进入后台)")
// 会话会在 App 回到前台后自动恢复
}
func sessionSuspensionEnded(_ session: NISession) {
print("UWB 会话恢复")
// 重新启动会话
if let config = session.configuration {
session.run(config)
}
}
func session(_ session: NISession,
didInvalidateWith error: Error) {
print("会话失效: \(error.localizedDescription)")
// 重新创建会话
self.session = nil
// 通知用户重新开始搜索
}
最佳实践
- 距离显示做平滑处理:使用指数移动平均(EMA),alpha 值设为 0.2-0.3。原始数据会有 5-10cm 的跳变,直接显示会让用户觉得不准。
- 当距离小于 1 米时,切换到声音提示(越近声音越急促),因为此时方向数据不稳定,视觉指引反而不如听觉直观。
- 提前在 MFi 门户注册你的配件类型,获取必要的认证。第三方 UWB 配件必须通过 MFi 认证才能和 iPhone 的 Nearby Interaction 框架通信。
还有什么值得关注
- iOS 15 的 Nearby Interaction 支持同时追踪多个配件(最多约 10 个),适合”钥匙、钱包、背包同时找”的场景。
- Apple 开放了 Nearby Interaction 的第三方配件规范给芯片厂商(NXP、Qorvo 等),预计会有大量 UWB 配件上市。
- Camera Assistance 模式需要用户授权相机权限,在 Info.plist 中添加
NSCameraUsageDescription。