Интеграция Nearby Interaction (Apple UWB) в iOS-приложение
Nearby Interaction — фреймворк Apple для определения точного расстояния и направления до другого iPhone или аксессуара с чипом U1/U2. Это не Bluetooth proximity, не iBeacon и не GPS. UWB (Ultra Wideband) работает на сантиметровой точности: приложение получает distance в метрах с точностью ±10–15 см и direction — 3D-вектор к устройству в пространстве (на iPhone 14 Pro и новее через двунаправленные антенны).
Используется для: точечного наведения в шеринге файлов и платежах, нахождения потерянных предметов (как AirTag), управления умным домом с привязкой к пространству, AR-приложений с реальной пространственной привязкой.
Ограничения, которые нужно знать до старта
Только iPhone 11 и новее. Чип U1 впервые появился в iPhone 11. iPhone SE (все поколения) — без UWB. iPad — без UWB (кроме специализированных конфигураций). Приложение обязано проверять NISession.deviceCapabilities.supportsPreciseDistanceMeasurement.
Фоновый режим. NISession работает только когда приложение на переднем плане. Нет исключений. Если нужно измерение в фоне — UWB не подходит, это аппаратное ограничение.
Два устройства, один сеанс. Для P2P-измерения оба устройства должны создать NISession и обменяться NIDiscoveryToken. Токен нельзя передать заранее — он генерируется при создании сессии и меняется при каждом перезапуске. Обмен токенами происходит через MultipeerConnectivity, Bluetooth, сервер — на ваш выбор.
Как устроена сессия
import NearbyInteraction
import MultipeerConnectivity
class UWBSessionManager: NSObject, NISessionDelegate {
private var niSession = NISession()
private var peerToken: NIDiscoveryToken?
override init() {
super.init()
niSession.delegate = self
}
func startSession(with peerToken: NIDiscoveryToken) {
let config = NINearbyPeerConfiguration(peerToken: peerToken)
config.isCameraAssistanceEnabled = true // включает Camera Assistance на iPhone 14 Pro+
niSession.run(config)
}
func session(_ session: NISession,
didUpdate nearbyObjects: [NINearbyObject]) {
guard let peer = nearbyObjects.first else { return }
if let distance = peer.distance {
print("Distance: \(distance) m")
}
if let direction = peer.direction {
print("Direction: \(direction)") // simd_float3
}
}
func session(_ session: NISession,
didInvalidateWith error: Error) {
// NIErrorCode.userDidNotAllow, .resourceUsageLimitReached, .sessionFailed
// при .resourceUsageLimitReached — просто перезапустить сессию
}
}
Обмен токенами через MultipeerConnectivity
Самый распространённый подход для P2P: используем MCSession для передачи токена, а затем запускаем NISession. Важно: NIDiscoveryToken нельзя передать как строку — он Codable, кодируем через NSKeyedArchiver:
let tokenData = try NSKeyedArchiver.archivedData(
withRootObject: niSession.discoveryToken!,
requiringSecureCoding: true
)
mcSession.send(tokenData, toPeers: peers, with: .reliable)
На принимающей стороне:
let token = try NSKeyedUnarchiver.unarchivedObject(
ofClass: NIDiscoveryToken.self,
from: data
)
Попытка передать токен через JSON-кодирование — не работает, NIDiscoveryToken не Encodable в стандартном смысле.
Camera Assistance
На iPhone 14 Pro и 15 серии доступен режим isCameraAssistanceEnabled = true. При этом система показывает нативный AR overlay поверх камеры, помогающий наводиться на устройство. Пользователь видит стрелку-указатель. Активируется только если пользователь дал разрешение на камеру. Добавляет задержку ~200 мс до получения первых direction-данных.
Что входит в работу
- Проверка совместимости устройства (
NIDeviceCapability) - Настройка
NISessionс конфигурацией для P2P или аксессуаров (NINearbyAccessoryConfiguration) - Механизм обмена
NIDiscoveryToken(через MultipeerConnectivity, Bluetooth или REST) - Обработка обновлений расстояния/направления в реальном времени
- Camera Assistance overlay
- Обработка ошибок и перезапуск сессии
- Тестирование на двух физических устройствах (симулятор UWB не поддерживает)
Сроки
5 дней. Тестирование требует двух реальных iPhone с U1/U2 — симулятор недостаточен. Стоимость рассчитывается индивидуально после анализа сценария использования.







