mcpField
A
apple-corelocation

apple-corelocation

github.com/ios-agent开发1255 次安装34 周前更新
代码仓库

关于 apple-corelocation

apple-corelocation 是面向 Apple 平台开发者的 CoreLocation 编程参考技能,涵盖定位、权限、地理围栏、地理编码和后台更新,并说明 iOS 17+ 的异步 API 用法。

主要功能

  1. 01提供 iOS 17+ 异步定位模式
  2. 02说明授权与权限配置
  3. 03涵盖区域监控和地理编码
  4. 04介绍后台定位与功耗优化
  5. 05列出 CoreLocation 常用 API

适用场景

  1. 01为 SwiftUI 应用实现实时定位
  2. 02处理定位权限与状态变化
  3. 03设置地理围栏或地址转换
  4. 04降低后台位置更新的功耗

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/ios-agent/iosagent.dev --skill apple-corelocation

安装后在 Claude Code 中输入/apple-corelocation确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
authorization.md
background.md
beacon-compass.md
geocoding.md
live-updates.md
location-manager.md
monitoring.md

详细介绍

Apple CoreLocation 技能

使用此技能编写正确、现代的 CoreLocation 代码。CoreLocation 提供地理位置、海拔、方向以及 iBeacon 邻近度服务。 它使用 Wi-Fi、GPS、蓝牙、磁力计、气压计和蜂窝网络硬件。

何时阅读参考文件

此 SKILL.md 包含必要模式和 API 速查内容。 如需深入了解实现细节,请阅读相应的参考文件:

主题参考文件阅读时机
实时更新和 async/await 模式references/live-updates.mdSwiftUI 应用、异步位置流、后台活动会话
授权和权限references/authorization.md权限流程、Info.plist 键、授权状态处理
区域监控和 CLMonitorreferences/monitoring.md地理围栏、条件监控、圆形区域
地理编码references/geocoding.md地址 ↔ 坐标转换、反向地理编码、CLPlacemark
iBeacon 和指南针references/beacon-compass.md信标测距、方向更新、磁力计
后台位置references/background.md后台更新、CLBackgroundActivitySession、电量优化
CLLocationManager APIreferences/location-manager.mdCLLocationManager 属性和方法的完整参考

现代 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? — 位置;若不可用则为 nil
  • isStationary: 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 的关键属性

属性类型描述
coordinateCLLocationCoordinate2D纬度和经度(WGS 84)
altitudeCLLocationDistance海平面以上的高度,单位为米
horizontalAccuracyCLLocationAccuracy精度,单位为米(负值 = 无效)
verticalAccuracyCLLocationAccuracy海拔精度,单位为米
speedCLLocationSpeed速度,单位为米/秒
courseCLLocationDirection相对于真北的角度
timestampDate确定位置的时间
floorCLFloor?所在建筑的楼层(如有)
sourceInformationCLLocationSourceInformation?位置信息来源

功耗优化指南

根据使用场景选择功耗效率最高的服务:

  1. 访问记录服务(startMonitoringVisits())——功耗效率最高。报告到访地点和停留时间。适用于:签到应用、旅行日志。

  2. 重大位置变化服务(startMonitoringSignificantLocationChanges())——低功耗,仅使用 Wi-Fi/蜂窝网络。适用于:大致位置跟踪。

  3. 标准位置服务(startUpdatingLocation())——可通过 desiredAccuracy 配置精度。适用于:导航、健身跟踪。

  4. 实时更新(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。

评论

支持 Markdown