Highlight
Core Location 在 visionOS 上采用与 iOS 相同的权限模型和 API,但”在使用中”的定义基于用户的视线方向而非前台状态:头显单独使用时定位精度约 100 米,附近 iPhone 可将精度提升至手机级别;窗口应用在用户视线移开后会在短暂宽限期内停止接收位置更新。
核心内容
权限模型:熟悉但需重新理解
(00:50)在 visionOS 上请求位置权限的方式与 iOS 完全一致。创建 CLLocationManager,调用 requestWhenInUseAuthorization(),并在 Info.plist 中设置 NSLocationWhenInUseUsageDescription 说明字符串。
(02:14)用户看到的授权弹窗也与 iOS 类似:可以选择允许一次、使用时允许或拒绝,还可以选择精确或模糊定位。但这里的”使用时允许”在空间计算平台上有完全不同的含义。
(02:52)关键原则:只在真正需要定位的上下文中请求权限。启动时就请求权限会降低用户授权的概率,也违背隐私设计原则。
定位精度:设备组合决定精度
(04:04)visionOS 设备单独使用时的定位精度约为 100 米,与 Mac 相当。这足够用于查找附近餐厅、公园等场景。
(04:24)但如果用户的 iPhone 在附近,两台设备之间的协同连接可以将定位精度提升到 iPhone 级别。这意味着你的应用需要根据当前精度调整行为——在 100 米精度下做精确导航没有意义。
“在使用中”的全新定义
(05:02)这是 session 最核心的内容。在 iPhone 上,“在使用中”等同于”应用在前台”。但在 visionOS 上,这个概念完全不同。
(05:33)对于全沉浸式应用,只要用户正在运行你的应用,就视为”在使用中”,可以获取位置更新。
(05:56)对于窗口应用,Core Location 只有在用户”最近看过”(looked at)应用时才认为它在”使用中”。如果用户视线移开,应用会在短暂宽限期(几秒钟)后停止接收位置更新。
(06:17)具体场景:
- 用户没有与任何应用交互:两个应用都收不到位置更新
- 用户看向左侧应用:左侧应用可以获取位置更新,右侧应用不行
- 用户将两个窗口移到一起,能同时看到:两个应用都可以获取位置更新
- 用户视线在左右应用间切换:短暂宽限期内两个应用都能获取更新
(07:33)应用未运行时不会收到任何位置更新,monitoring API(如区域监听)的更新也不会被投递。这与 iOS 的后台行为有本质区别。
兼容模式下的行为
(07:54)如果你的 iPhone 或 iPad 应用直接在 visionOS 上运行(兼容模式),需要注意以下变化:
- 请求 Always 授权会被重定向为 WhenInUse 授权
- Settings 中不会出现 Always 选项
- 区域监听(CLMonitor/CLCircularRegion)不会收到事件
- 后台位置更新不可用
如果你的 iOS 应用假设某些 API 始终可用,可能会在 visionOS 上出现意外行为。建议在发布前测试兼容模式下的表现。
详细内容
请求位置更新的代码
(00:54)使用 CLLocationUpdate 获取实时位置更新:
import CoreLocation
actor LocationActor {
func startUpdates() async {
// 请求权限
let manager = CLLocationManager()
manager.requestWhenInUseAuthorization()
// 获取实时位置更新
for await update in CLLocationUpdate.liveUpdates() {
if let location = update.location {
print("Latitude: \(location.coordinate.latitude)")
print("Longitude: \(location.coordinate.longitude)")
print("Accuracy: \(location.horizontalAccuracy) meters")
}
}
}
}
关键点:
CLLocationUpdate.liveUpdates()返回异步序列,符合 Swift Concurrency 模式- 需要在 Info.plist 中设置
NSLocationWhenInUseUsageDescription - 检查
horizontalAccuracy来判断当前精度是否满足需求
根据精度调整应用行为
func handleLocationUpdate(_ location: CLLocation) {
let accuracy = location.horizontalAccuracy
if accuracy <= 10 {
// iPhone 级别精度,可以做精确导航
showDetailedNavigation()
} else if accuracy <= 100 {
// 头显单独使用时的精度
showNearbyPlaces()
} else {
// 精度较低,只显示大致区域
showGeneralArea()
}
}
视线感知的窗口应用设计
(06:17)窗口应用需要适应视线驱动的位置更新模式:
import SwiftUI
import CoreLocation
struct LocationView: View {
@StateObject private var locationModel = LocationModel()
var body: some View {
VStack {
if let location = locationModel.lastLocation {
Text("Current: \(location.coordinate.latitude), \(location.coordinate.longitude)")
Text("Accuracy: ±\(Int(location.horizontalAccuracy))m")
.foregroundColor(accuracyColor(location.horizontalAccuracy))
} else {
Text("Looking away - location updates paused")
.foregroundColor(.secondary)
}
}
.task {
await locationModel.startMonitoring()
}
}
func accuracyColor(_ accuracy: CLLocationAccuracy) -> Color {
if accuracy <= 10 { return .green }
if accuracy <= 100 { return .yellow }
return .orange
}
}
@MainActor
class LocationModel: ObservableObject {
@Published var lastLocation: CLLocation?
func startMonitoring() async {
let manager = CLLocationManager()
manager.requestWhenInUseAuthorization()
for await update in CLLocationUpdate.liveUpdates() {
if let location = update.location {
self.lastLocation = location
}
}
}
}
关键点:
- 使用
.task修饰符在视图出现时启动位置监听 - 当用户视线移开时,更新会暂停,UI 应显示相应状态
@MainActor确保 UI 更新在主线程执行
核心启发
-
设计视线感知的定位体验
- 做什么:为 visionOS 窗口应用设计适应视线驱动位置更新的 UI,明确显示定位活跃状态
- 为什么值得做:用户视线移开时位置更新会暂停,UI 需要让用户理解这个行为,避免困惑
- 怎么开始:在视图中添加位置状态指示器,使用
.task管理位置更新的生命周期,处理更新暂停时的 UI 状态
-
根据精度动态调整功能
- 做什么:根据
horizontalAccuracy的值动态调整应用提供的功能粒度 - 为什么值得做:头显单独使用时 100 米精度与 iPhone 配合时的米级精度差异巨大,同样的 UI 在两种精度下体验完全不同
- 怎么开始:在获取位置更新时检查精度值,为不同精度范围设计不同的功能层级和 UI 表现
- 做什么:根据
-
测试兼容模式下的位置行为
- 做什么:在 visionOS 模拟器和设备上测试现有 iOS 应用在兼容模式下的位置相关功能
- 为什么值得做:Always 授权被降级、区域监听不工作、后台更新不可用,这些变化可能导致现有应用行为异常
- 怎么开始:在 Xcode 中选择 visionOS 模拟器运行现有 iOS 应用,测试位置请求、区域监听和后台行为
-
利用设备协同提升定位体验
- 做什么:设计功能时考虑 iPhone 在附近的高精度场景和头显单独使用的低精度场景
- 为什么值得做:两种场景都是真实用户会遇到的,应用应该在两种情况下都提供合理的体验
- 怎么开始:在 UI 中提示用户将 iPhone 放在附近以获得更精确的定位,同时为低精度场景设计降级方案
关联 Session
- Meet Core Location Monitor — 全新的 CLMonitor API,用于监听地理区域和 Beacon 事件
- Discover streamlined location updates — CLLocationUpdate 的实时位置更新 API
- Develop your first immersive app — visionOS 沉浸式应用开发入门
- Meet SwiftUI for spatial computing — SwiftUI 在空间计算平台上的适配
评论
GitHub Issues · utterances