认识 Nearby Interaction 框架
Meet Nearby Interaction
2020年6月24日
一句话判断
Nearby Interaction 是苹果给 UWB(超宽带)芯片准备的开发者接口——两台支持 U1 芯片的设备可以实时感知彼此的方向和距离,精度达到厘米级,做寻物、空间交互的 app 终于有了靠谱的底层支持。
这场 Session 讲了什么
iOS 14 引入了 NearbyInteraction 框架,利用 Apple U1 芯片的超宽带(Ultra Wideband)技术实现设备间的精确定位。
核心能力:两台设备(当前仅 iPhone 11 及以上的机型有 U1 芯片)可以通过 Nearby Interaction 实时获取彼此的距离(以米为单位,精度约 10 厘米)和相对方向(水平角度)。Session 演示了如何建立 session、交换 token、以及实时接收距离和角度更新。
使用场景包括:找到附近朋友的精确位置、两个设备之间的空间交互游戏、AR 中的设备配对定位。数据更新频率约为每秒 10 次,足够用于实时 UI 更新。
值得深挖的点
UWB 与蓝牙/WiFi 定位的本质区别
蓝牙 RSSI 只能估算距离(误差几米),完全无法确定方向。Wifi RTT 可以做到亚米级距离但方向精度很差。UWB 的飞行时间(ToF)测距精度在 10 厘米以内,而且可以通过天线阵列测量到达角度(AoA),提供方向信息。这是「大概在那边」和「就在你左手边 30 度、2 米远」的区别。
Token 交换机制
Nearby Interaction 需要两台设备先交换一个 NIDiscoveryToken。这个交换可以通过任何通道完成:蓝牙、WiFi、甚至 CloudKit。Token 本身只是一小段数据,不包含敏感信息。交换完成后,双方都调用 NINearbyPeerConfiguration 建立会话,然后开始接收距离和角度更新。
代码片段
import NearbyInteraction
class NearbyManager: NSObject, NISessionDelegate {
var session: NISession?
func startDiscovery() {
// 检查设备是否支持 Nearby Interaction
guard NISession.isSupported else {
print("此设备不支持 Nearby Interaction")
return
}
session = NISession()
session?.delegate = self
// 获取自己的 discovery token 并发送给对方
guard let token = session?.discoveryToken else { return }
sendTokenToPeer(token)
}
// 收到对方的 token 后建立会话
func handlePeerToken(_ peerToken: NIDiscoveryToken) {
let config = NINearbyPeerConfiguration(peerToken: peerToken)
session?.run(config)
}
// MARK: - NISessionDelegate
func session(_ session: NISession, didUpdate nearbyObjects: [NINearbyObject]) {
guard let peer = nearbyObjects.first else { return }
// 距离(单位:米)
if let distance = peer.distance {
print("距离: \(String(format: "%.2f", distance)) 米")
}
// 方向(水平角度,单位:弧度)
if let direction = peer.direction {
let angleDegrees = direction.x * 180 / .pi
print("方向: \(String(format: "%.1f", angleDegrees)) 度")
}
}
func session(_ session: NISession, didRemove nearbyObjects: [NINearbyObject], reason: NINearbyObject.RemovalReason) {
switch reason {
case .peerEnded:
print("对方结束了会话")
case .timeout:
print("连接超时")
default:
break
}
}
}
// 通过 MultipeerConnectivity 交换 token
import MultipeerConnectivity
class TokenExchangeManager: NSObject, MCSessionDelegate {
let session: MCSession
let peerID = MCPeerID(displayName: UIDevice.current.name)
override init() {
session = MCSession(peer: peerID)
super.init()
session.delegate = self
}
func sendTokenToPeer(_ token: NIDiscoveryToken) {
guard !session.connectedPeers.isEmpty else { return }
// 将 token 序列化并发送
let data = try! NSKeyedArchiver.archivedData(withRootObject: token, requiringSecureCoding: true)
try? session.send(data, toPeers: session.connectedPeers, with: .reliable)
}
func session(_ session: MCSession, didReceive data: Data, fromPeer peerID: MCPeerID) {
// 收到对方的 token
if let token = try? NSKeyedUnarchiver.unarchivedObject(ofClass: NIDiscoveryToken.self, from: data) {
// 传递给 NearbyManager 建立会话
handlePeerToken(token)
}
}
}
最佳实践
- Token 交换用 MultipeerConnectivity。虽然理论上任何通道都行,但 MCSession 是最简单的选择——自动处理设备发现和数据传输,不需要自己搭服务器。
- 距离数据要做平滑处理。UWB 测距有 10cm 左右的抖动,直接用原始数据驱动 UI 会导致频繁跳动。用指数移动平均(EMA)平滑距离值。
- 在后台无法使用 Nearby Interaction。UWB 需要前台运行状态。如果 app 进入后台,session 会暂停,回到前台后需要重新
run()。
还有什么值得关注
- 目前只有 iPhone 11/12 系列和 Apple Watch Series 6 有 U1 芯片,不支持 UWB 的设备会回退到蓝牙精度。
- Nearby Interaction 不传输用户身份信息,只提供距离和角度,隐私安全性有保障。
- 苹果的 AirTag 就是基于 UWB 技术,配合
FindItems框架可以在 app 中集成 AirTag 的精确查找功能。