apple-corelocation

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Apple CoreLocation Skill

Apple CoreLocation 参考技能

Use this skill to write correct, modern CoreLocation code. CoreLocation provides services for geographic location, altitude, orientation, and proximity to iBeacons. It uses Wi-Fi, GPS, Bluetooth, magnetometer, barometer, and cellular hardware.
使用此技能编写规范、现代化的CoreLocation代码。CoreLocation提供地理位置、海拔、方向以及与iBeacon的距离检测服务,它会使用Wi-Fi、GPS、蓝牙、磁力计、气压计和蜂窝网络硬件。

When to Read Reference Files

何时阅读参考文档

This SKILL.md contains the essential patterns and quick-reference API surface. For deeper implementation details, read the appropriate reference file:
TopicReference FileWhen to Read
Live Updates & async/await patterns
references/live-updates.md
SwiftUI apps, async location streams, background activity sessions
Authorization & Permissions
references/authorization.md
Permission flows, Info.plist keys, authorization status handling
Region Monitoring & CLMonitor
references/monitoring.md
Geofencing, condition monitoring, circular regions
Geocoding
references/geocoding.md
Address ↔ coordinate conversion, reverse geocoding, CLPlacemark
iBeacon & Compass
references/beacon-compass.md
Beacon ranging, heading updates, magnetometer
Background Location
references/background.md
Background updates, CLBackgroundActivitySession, power optimization
CLLocationManager API
references/location-manager.md
Full property/method reference for CLLocationManager
本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的完整属性/方法参考

Modern CoreLocation (iOS 17+): Prefer Async/Await

现代化CoreLocation(iOS 17+):优先使用Async/Await

Since iOS 17, CoreLocation supports Swift concurrency. Prefer the modern async API over the legacy delegate-based approach for new projects.
自iOS 17起,CoreLocation支持Swift并发。对于新项目,优先使用现代化的异步API,而非传统的基于代理的方式。

Getting Live Location Updates (Recommended Pattern)

获取实时位置更新(推荐模式)

swift
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
    }
}
The system automatically prompts for authorization when iteration begins if status is
.notDetermined
. No explicit
requestWhenInUseAuthorization()
call is needed with this pattern, but you may still call it for controlled timing.
swift
import CoreLocation

let updates = CLLocationUpdate.liveUpdates()

for try await update in updates {
    if let location = update.location {
        // 处理位置信息
        print("纬度: \(location.coordinate.latitude), 经度: \(location.coordinate.longitude)")
    }
    if update.authorizationDenied {
        // 处理授权被拒绝的情况
    }
    if update.authorizationRequestInProgress {
        // 系统正在显示授权对话框
    }
}
如果授权状态为
.notDetermined
,当开始迭代时系统会自动提示用户授权。使用此模式无需显式调用
requestWhenInUseAuthorization()
,但你也可以主动调用以控制时机。

Live Updates with Accuracy Configuration

带精度配置的实时更新

swift
// 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)
swift
// 高精度(GPS,功耗较高)
let updates = CLLocationUpdate.liveUpdates(.default)

// 低功耗选项
let updates = CLLocationUpdate.liveUpdates(.automotiveNavigation)
let updates = CLLocationUpdate.liveUpdates(.otherNavigation)
let updates = CLLocationUpdate.liveUpdates(.fitness)
let updates = CLLocationUpdate.liveUpdates(.airborne)

CLLocationUpdate Properties

CLLocationUpdate 属性

  • location: CLLocation?
    — The location, or nil if unavailable
  • isStationary: Bool
    — Whether the device is stationary
  • authorizationDenied: Bool
    — Authorization was denied
  • authorizationDeniedGlobally: Bool
    — Location services disabled system-wide
  • authorizationRequestInProgress: Bool
    — Auth dialog is being shown
  • insufficientlyInUse: Bool
    — App lacks sufficient "in use" state
  • locationUnavailable: Bool
    — Location data temporarily unavailable
  • accuracyLimited: Bool
    — Accuracy authorization is reduced
  • location: CLLocation?
    — 位置信息,不可用时为nil
  • isStationary: Bool
    — 设备是否处于静止状态
  • authorizationDenied: Bool
    — 授权已被拒绝
  • authorizationDeniedGlobally: Bool
    — 系统级位置服务已禁用
  • authorizationRequestInProgress: Bool
    — 正在显示授权对话框
  • insufficientlyInUse: Bool
    — 应用未获得足够的“使用中”状态权限
  • locationUnavailable: Bool
    — 位置数据暂时不可用
  • accuracyLimited: Bool
    — 授权精度已降低

SwiftUI Integration Pattern

SwiftUI 集成模式

swift
@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
    }
}
swift
@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
    }
}

Authorization Quick Reference

授权快速参考

Info.plist Keys (Required)

Info.plist 必要键值

KeyWhen to Use
NSLocationWhenInUseUsageDescription
App uses location while in foreground
NSLocationAlwaysAndWhenInUseUsageDescription
App needs location in background too
NSLocationDefaultAccuracyReduced
Request reduced accuracy by default
使用场景
NSLocationWhenInUseUsageDescription
应用在前台使用位置信息
NSLocationAlwaysAndWhenInUseUsageDescription
应用需要在后台也使用位置信息
NSLocationDefaultAccuracyReduced
默认请求降低精度的位置信息

Authorization Status Values (
CLAuthorizationStatus
)

授权状态值(
CLAuthorizationStatus

ValueMeaning
.notDetermined
User hasn't been asked yet
.restricted
App cannot use location (e.g., parental controls)
.denied
User explicitly denied
.authorizedWhenInUse
App can use location while in foreground
.authorizedAlways
App can use location at any time
含义
.notDetermined
尚未询问用户授权
.restricted
应用无法使用位置服务(如受家长控制限制)
.denied
用户明确拒绝授权
.authorizedWhenInUse
应用可在前台使用位置信息
.authorizedAlways
应用可随时使用位置信息

Requesting Authorization

请求授权

swift
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")
swift
let manager = CLLocationManager()

// 仅前台访问权限
manager.requestWhenInUseAuthorization()

// 后台访问权限(需先获得“使用期间”权限)
manager.requestAlwaysAuthorization()

// 请求临时高精度授权(当用户已授予降低精度权限时)
manager.requestTemporaryFullAccuracyAuthorization(withPurposeKey: "MyPurposeKey")

Condition Monitoring with CLMonitor (iOS 17+)

基于CLMonitor的条件监控(iOS 17+)

swift
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
    }
}
swift
let monitor = await CLMonitor("myMonitor")

// 添加圆形地理区域条件
await monitor.add(
    CLMonitor.CircularGeographicCondition(center: coordinate, radius: 200),
    identifier: "coffee-shop"
)

// 监听事件
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
    }
}

Geocoding Quick Reference

地理编码快速参考

swift
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)
    }
}
swift
let geocoder = CLGeocoder()

// 逆地理编码:坐标 → 地址
geocoder.reverseGeocodeLocation(location) { placemarks, error in
    if let placemark = placemarks?.first {
        print(placemark.locality ?? "Unknown city")
    }
}

// 正向地理编码:地址 → 坐标
geocoder.geocodeAddressString("1 Apple Park Way, Cupertino") { placemarks, error in
    if let location = placemarks?.first?.location {
        print(location.coordinate)
    }
}

CLLocation Key Properties

CLLocation 核心属性

PropertyTypeDescription
coordinate
CLLocationCoordinate2D
Latitude and longitude (WGS 84)
altitude
CLLocationDistance
Meters above sea level
horizontalAccuracy
CLLocationAccuracy
Accuracy in meters (negative = invalid)
verticalAccuracy
CLLocationAccuracy
Altitude accuracy in meters
speed
CLLocationSpeed
Meters per second
course
CLLocationDirection
Degrees relative to true north
timestamp
Date
When the location was determined
floor
CLFloor?
Floor of a building, if available
sourceInformation
CLLocationSourceInformation?
Info about the location source
属性类型描述
coordinate
CLLocationCoordinate2D
纬度和经度(WGS 84标准)
altitude
CLLocationDistance
海拔高度(米,相对于海平面)
horizontalAccuracy
CLLocationAccuracy
水平精度(米,负值表示无效)
verticalAccuracy
CLLocationAccuracy
垂直精度(米)
speed
CLLocationSpeed
移动速度(米/秒)
course
CLLocationDirection
航向(相对于真北的角度,度)
timestamp
Date
位置信息的获取时间
floor
CLFloor?
所在楼层(如果可用)
sourceInformation
CLLocationSourceInformation?
位置信息来源的相关信息

Power Optimization Guidelines

功耗优化指南

Choose the most power-efficient service for your use case:
  1. Visits service (
    startMonitoringVisits()
    ) — Most power-efficient. Reports places visited and time spent. Good for: check-in apps, travel logs.
  2. Significant-change service (
    startMonitoringSignificantLocationChanges()
    ) — Low power, uses Wi-Fi/cellular only. Good for: approximate location tracking.
  3. Standard location service (
    startUpdatingLocation()
    ) — Configurable accuracy via
    desiredAccuracy
    . Good for: navigation, fitness tracking.
  4. Live updates (
    CLLocationUpdate.liveUpdates()
    ) — Modern async API with configurable activity types. Good for: any new project on iOS 17+.
根据你的使用场景选择最节能的服务:
  1. 到访服务
    startMonitoringVisits()
    )—— 最节能,报告用户到访的地点和停留时间。适用于:签到应用、旅行日志。
  2. 重要位置变更服务
    startMonitoringSignificantLocationChanges()
    )—— 低功耗,仅使用Wi-Fi/蜂窝网络。适用于:大致位置追踪。
  3. 标准位置服务
    startUpdatingLocation()
    )—— 精度可通过
    desiredAccuracy
    配置。适用于:导航、健身追踪。
  4. 实时更新
    CLLocationUpdate.liveUpdates()
    )—— 现代化异步API,支持配置活动类型。适用于:iOS 17+的所有新项目。

Desired Accuracy Constants

目标精度常量

ConstantDescription
kCLLocationAccuracyBestForNavigation
Highest precision, most power
kCLLocationAccuracyBest
Best available accuracy
kCLLocationAccuracyNearestTenMeters
Within ~10 meters
kCLLocationAccuracyHundredMeters
Within ~100 meters
kCLLocationAccuracyKilometer
Within ~1 km
kCLLocationAccuracyThreeKilometers
Within ~3 km
kCLLocationAccuracyReduced
Deliberately reduced accuracy
常量描述
kCLLocationAccuracyBestForNavigation
最高精度,功耗最大
kCLLocationAccuracyBest
可用的最佳精度
kCLLocationAccuracyNearestTenMeters
精度约10米以内
kCLLocationAccuracyHundredMeters
精度约100米以内
kCLLocationAccuracyKilometer
精度约1公里以内
kCLLocationAccuracyThreeKilometers
精度约3公里以内
kCLLocationAccuracyReduced
刻意降低的精度

Platform Considerations

平台注意事项

  • visionOS: Location services are limited. Background updates are not supported. Region monitoring methods do nothing for compatible iPad/iPhone apps running in visionOS.
  • macOS: Apps are not suspended in background, so no special background capability needed.
  • watchOS: Supports background location with capability. Use
    CLBackgroundActivitySession
    .
  • Widgets: Check
    isAuthorizedForWidgetUpdates
    for widget eligibility.
  • visionOS:位置服务受限,不支持后台更新。兼容的iPad/iPhone应用在visionOS中运行时,区域监控方法无效。
  • macOS:应用在后台不会被挂起,因此无需特殊的后台权限。
  • watchOS:支持带权限的后台位置服务,需使用
    CLBackgroundActivitySession
  • 小组件:需检查
    isAuthorizedForWidgetUpdates
    以确认小组件是否具备使用权限。

Common Pitfalls

常见误区

  • Always check
    horizontalAccuracy
    — negative values mean the coordinate is invalid.
  • Do not assume location is immediately available after starting services.
  • Handle authorization changes gracefully; users can revoke at any time via Settings.
  • Geocoder requests are rate-limited; cache results and do not geocode on every location update.
  • The system can pause location updates automatically. Set
    pausesLocationUpdatesAutomatically
    and
    activityType
    to help CoreLocation make good decisions.
  • For background updates on iOS: add the "Location updates" background mode capability AND set
    allowsBackgroundLocationUpdates = true
    on the location manager.
  • 始终检查
    horizontalAccuracy
    ——负值表示坐标无效。
  • 不要假设启动服务后位置信息会立即可用。
  • 优雅处理授权变更;用户可随时通过设置撤销授权。
  • 地理编码请求有频率限制;请缓存结果,不要在每次位置更新时都进行地理编码。
  • 系统可能会自动暂停位置更新。设置
    pausesLocationUpdatesAutomatically
    activityType
    可帮助CoreLocation做出合理决策。
  • 对于iOS后台更新:需添加“位置更新”后台模式权限,并且在位置管理器上设置
    allowsBackgroundLocationUpdates = true