关于 apple-corelocation
apple-corelocation 是面向 Apple 平台开发者的 CoreLocation 编程参考技能,涵盖定位、权限、地理围栏、地理编码和后台更新,并说明 iOS 17+ 的异步 API 用法。
主要功能
- 01提供 iOS 17+ 异步定位模式
- 02说明授权与权限配置
- 03涵盖区域监控和地理编码
- 04介绍后台定位与功耗优化
- 05列出 CoreLocation 常用 API
适用场景
- 01为 SwiftUI 应用实现实时定位
- 02处理定位权限与状态变化
- 03设置地理围栏或地址转换
- 04降低后台位置更新的功耗
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ ios-agent/ iosagent.dev --skill apple-corelocation安装后在 Claude Code 中输入/apple-corelocation确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/authorization.mdbackground.mdbeacon-compass.mdgeocoding.mdlive-updates.mdlocation-manager.mdmonitoring.md详细介绍
Apple CoreLocation 技能
使用此技能编写正确、现代的 CoreLocation 代码。CoreLocation 提供地理位置、海拔、方向以及 iBeacon 邻近度服务。 它使用 Wi-Fi、GPS、蓝牙、磁力计、气压计和蜂窝网络硬件。
何时阅读参考文件
此 SKILL.md 包含必要模式和 API 速查内容。 如需深入了解实现细节,请阅读相应的参考文件:
| 主题 | 参考文件 | 阅读时机 |
|---|---|---|
| 实时更新和 async/await 模式 | references/live-updates.md | SwiftUI 应用、异步位置流、后台活动会话 |
| 授权和权限 | references/authorization.md | 权限流程、Info.plist 键、授权状态处理 |
| 区域监控和 CLMonitor | references/monitoring.md | 地理围栏、条件监控、圆形区域 |
| 地理编码 | references/geocoding.md | 地址 ↔ 坐标转换、反向地理编码、CLPlacemark |
| iBeacon 和指南针 | references/beacon-compass.md | 信标测距、方向更新、磁力计 |
| 后台位置 | references/background.md | 后台更新、CLBackgroundActivitySession、电量优化 |
| CLLocationManager API | references/location-manager.md | CLLocationManager 属性和方法的完整参考 |
现代 CoreLocation(iOS 17+):优先使用 Async/Await
从 iOS 17 开始,CoreLocation 支持 Swift 并发。对于新项目,优先使用现代异步 API, 而不是基于代理的旧方法。
获取实时位置更新(推荐模式)
import CoreLocation
let updates = CLLocationUpdate.liveUpdates()
for try await update in updates {
if let location = update.location {
// Process location
print("Lat: \(location.coordinate.latitude), Lon: \(location.coordinate.longitude)")
}
if update.authorizationDenied {
// Handle denied authorization
}
if update.authorizationRequestInProgress {
// System is showing the authorization dialog
}
}
如果状态为 .notDetermined,系统会在开始迭代时自动请求授权。此模式下无需显式调用 requestWhenInUseAuthorization(),
但你仍可调用它来控制请求时机。
配置精度的实时更新
// High accuracy (GPS, more power)
let updates = CLLocationUpdate.liveUpdates(.default)
// Power-efficient options
let updates = CLLocationUpdate.liveUpdates(.automotiveNavigation)
let updates = CLLocationUpdate.liveUpdates(.otherNavigation)
let updates = CLLocationUpdate.liveUpdates(.fitness)
let updates = CLLocationUpdate.liveUpdates(.airborne)
CLLocationUpdate 属性
location: CLLocation?— 位置;若不可用则为 nilisStationary: Bool— 设备是否处于静止状态authorizationDenied: Bool— 授权已被拒绝authorizationDeniedGlobally: Bool— 系统范围的位置服务已停用authorizationRequestInProgress: Bool— 正在显示授权对话框insufficientlyInUse: Bool— 应用未处于足够的“使用中”状态locationUnavailable: Bool— 位置数据暂时不可用accuracyLimited: Bool— 精度授权已降低
SwiftUI 集成模式
@MainActor
class LocationsHandler: ObservableObject {
static let shared = LocationsHandler()
private let manager: CLLocationManager
private var background: CLBackgroundActivitySession?
@Published var lastLocation = CLLocation()
@Published var isStationary = false
@Published var updatesStarted: Bool = UserDefaults.standard.bool(forKey: "liveUpdatesStarted") {
didSet { UserDefaults.standard.set(updatesStarted, forKey: "liveUpdatesStarted") }
}
private init() {
self.manager = CLLocationManager()
}
func startLocationUpdates() {
if self.manager.authorizationStatus == .notDetermined {
self.manager.requestWhenInUseAuthorization()
}
Task {
do {
self.updatesStarted = true
let updates = CLLocationUpdate.liveUpdates()
for try await update in updates {
if !self.updatesStarted { break }
if let loc = update.location {
self.lastLocation = loc
self.isStationary = update.isStationary
}
}
} catch {
print("Could not start location updates")
}
}
}
func stopLocationUpdates() {
self.updatesStarted = false
}
}
授权速查
Info.plist 键(必需)
| 键 | 使用时机 |
|---|---|
NSLocationWhenInUseUsageDescription | 应用在前台使用位置 |
NSLocationAlwaysAndWhenInUseUsageDescription | 应用在后台也需要位置信息 |
NSLocationDefaultAccuracyReduced | 默认请求降低精度 |
授权状态值(CLAuthorizationStatus)
| 值 | 含义 |
|---|---|
.notDetermined | 尚未向用户请求授权 |
.restricted | 应用无法使用位置(例如,家长控制) |
.denied | 用户明确拒绝 |
.authorizedWhenInUse | 应用可在前台使用位置 |
.authorizedAlways | 应用可随时使用位置 |
请求授权
let manager = CLLocationManager()
// For foreground-only access
manager.requestWhenInUseAuthorization()
// For background access (after getting "When In Use" first)
manager.requestAlwaysAuthorization()
// For temporary full accuracy (when user granted reduced accuracy)
manager.requestTemporaryFullAccuracyAuthorization(withPurposeKey: "MyPurposeKey")
使用 CLMonitor 监控条件(iOS 17+)
let monitor = await CLMonitor("myMonitor")
// Add a circular geographic condition
await monitor.add(
CLMonitor.CircularGeographicCondition(center: coordinate, radius: 200),
identifier: "coffee-shop"
)
// Observe events
for try await event in await monitor.events {
switch event.state {
case .satisfied:
print("Entered region: \(event.identifier)")
case .unsatisfied:
print("Exited region: \(event.identifier)")
default:
break
}
}
地理编码速查
let geocoder = CLGeocoder()
// Reverse geocode: coordinate → address
geocoder.reverseGeocodeLocation(location) { placemarks, error in
if let placemark = placemarks?.first {
print(placemark.locality ?? "Unknown city")
}
}
// Forward geocode: address → coordinate
geocoder.geocodeAddressString("1 Apple Park Way, Cupertino") { placemarks, error in
if let location = placemarks?.first?.location {
print(location.coordinate)
}
}
CLLocation 的关键属性
| 属性 | 类型 | 描述 |
|---|---|---|
coordinate | CLLocationCoordinate2D | 纬度和经度(WGS 84) |
altitude | CLLocationDistance | 海平面以上的高度,单位为米 |
horizontalAccuracy | CLLocationAccuracy | 精度,单位为米(负值 = 无效) |
verticalAccuracy | CLLocationAccuracy | 海拔精度,单位为米 |
speed | CLLocationSpeed | 速度,单位为米/秒 |
course | CLLocationDirection | 相对于真北的角度 |
timestamp | Date | 确定位置的时间 |
floor | CLFloor? | 所在建筑的楼层(如有) |
sourceInformation | CLLocationSourceInformation? | 位置信息来源 |
功耗优化指南
根据使用场景选择功耗效率最高的服务:
-
访问记录服务(
startMonitoringVisits())——功耗效率最高。报告到访地点和停留时间。适用于:签到应用、旅行日志。 -
重大位置变化服务(
startMonitoringSignificantLocationChanges())——低功耗,仅使用 Wi-Fi/蜂窝网络。适用于:大致位置跟踪。 -
标准位置服务(
startUpdatingLocation())——可通过desiredAccuracy配置精度。适用于:导航、健身跟踪。 -
实时更新(
CLLocationUpdate.liveUpdates())——支持配置活动类型的现代异步 API。适用于:所有运行于 iOS 17+ 的新项目。
所需精度常量
| 常量 | 描述 |
|---|---|
kCLLocationAccuracyBestForNavigation | 最高精度,功耗最大 |
kCLLocationAccuracyBest | 可用的最佳精度 |
kCLLocationAccuracyNearestTenMeters | 精度约为 10 米 |
kCLLocationAccuracyHundredMeters | 精度约为 100 米 |
kCLLocationAccuracyKilometer | 精度约为 1 公里 |
kCLLocationAccuracyThreeKilometers | 精度约为 3 公里 |
kCLLocationAccuracyReduced | 有意降低的精度 |
平台注意事项
- visionOS:位置服务受到限制。不支持后台更新。在 visionOS 中运行的兼容 iPad/iPhone 应用调用区域监控方法时不会执行任何操作。
- macOS:应用在后台不会被挂起,因此无需特殊的后台功能。
- watchOS:支持通过功能启用后台位置服务。请使用
CLBackgroundActivitySession。 - 小组件:检查
isAuthorizedForWidgetUpdates,确认小组件是否符合条件。
常见问题
- 始终检查
horizontalAccuracy——负值表示坐标无效。 - 不要假设启动服务后就能立即获取位置。
- 妥善处理授权变更;用户随时可以通过“设置”撤销授权。
- 地理编码请求有频率限制;请缓存结果,不要在每次位置更新时都进行地理编码。
- 系统可能会自动暂停位置更新。设置
pausesLocationUpdatesAutomatically和activityType,以帮助 CoreLocation 做出合适的决策。 - 在 iOS 上启用后台更新:添加“位置更新”后台模式功能,并在位置管理器上设置
allowsBackgroundLocationUpdates = true。