94、Core Location 功能详解与应用实践

Core Location 功能详解与应用实践

1. 授权状态处理

根视图控制器可作为位置管理器的代理,实现 locationManager(_:didChangeAuthorizationStatus:) 方法来调用 ManagerHolder 中存储的函数:

func locationManager(_ manager: CLLocationManager,
    didChangeAuthorization status: CLAuthorizationStatus) {
        switch status {
        case .authorizedAlways, .authorizedWhenInUse:
            self.managerHolder.doThisWhenAuthorized?()
            self.managerHolder.doThisWhenAuthorized = nil
        default: break
        }
}

在跟踪位置前调用 ManagerHolder checkForLocationAccess 方法,若传入完成函数,若已获授权则立即调用该函数;若状态为 .notDetermined 且弹出授权请求提示框,用户授权后会调用该函数。

2. 位置跟踪

2.1 基本流程

使用位置管理器跟踪用户位置,需确保位置管理器有代理,按需进一步配置,然后调用 startUpdatingLocation 方法。位置管理器会不断调用代理的 locationManager(_:didUpdateLocations:) 方法,直到调用 stopUpdatingLocation 停止跟踪。

graph LR
    A[设置代理] --> B[配置位置管理器]
    B --> C[调用 startUpdatingLocation]
    C --> D[不断调用 didUpdateLocations]
    D --> E{是否停止跟踪}
    E -- 是 --> F[调用 stopUpdatingLocation]
    E -- 否 --> D

2.2 配置属性

属性 说明 可选值
desiredAccuracy 期望的定位精度 kCLLocationAccuracyBestForNavigation kCLLocationAccuracyBest kCLLocationAccuracyNearestTenMeters kCLLocationAccuracyHundredMeters kCLLocationAccuracyKilometer kCLLocationAccuracyThreeKilometers
distanceFilter 距离过滤器,设备移动指定距离才报告位置 以米为单位,设置为 kCLDistanceFilterNone 可关闭过滤器
pausesLocationUpdatesAutomatically 是否自动暂停位置更新 Bool 类型,默认 true ,与 activityType 相关

2.3 示例代码

self.managerHolder.checkForLocationAccess {
    self.locman.desiredAccuracy = kCLLocationAccuracyBest
    self.locman.distanceFilter = kCLDistanceFilterNone
    self.locman.activityType = .other
    self.locman.pausesLocationUpdatesAutomatically = false
    self.locman.startUpdatingLocation()
}

locationManager(_:didUpdateLocations:) 方法中处理位置更新:

let REQ_ACC : CLLocationAccuracy = 10
func locationManager(_ manager: CLLocationManager,
    didUpdateLocations locations: [CLLocation]) {
        let loc = locations.last!
        let acc = loc.horizontalAccuracy
        print(acc)
        if acc < 0 || acc > REQ_ACC {
            return // wait for the next one
        }
        let coord = loc.coordinate
        print("You are at \(coord.latitude) \(coord.longitude)")
}

3. 获取单次位置

常见错误做法是调用 startUpdatingLocation 后在 locationManager(_:didUpdateLocations:) 中立即停止更新,这可能无法获取准确位置。正确做法是调用 requestLocation 方法:

self.locman.desiredAccuracy = kCLLocationAccuracyBest
self.locman.requestLocation()

locationManager(_:didUpdateLocations:) 中处理:

func locationManager(manager: CLLocationManager,
    didUpdateLocations locations: [CLLocation]) {
        let loc = locations.last!
        let coord = loc.coordinate
        print("You are at \(coord.latitude) \(coord.longitude)")
}

需注意,调用 requestLocation 不会立即获取准确位置,且若短时间内多次调用可能返回缓存值。

4. 后台位置跟踪

4.1 连续后台位置跟踪

类似于后台播放声音,需在 Info.plist 中设置 “Required background modes” 包含 location ,并将位置管理器的 allowsBackgroundLocationUpdates 设置为 true
- 授权类型影响
- When In Use :设备通过蓝色双倍高度状态栏提醒用户应用在进行后台位置跟踪,用户可点击将应用调至前台。
- Always :默认不显示蓝色状态栏,若设置 showsBackgroundLocationIndicator true 则显示。
- 节能建议
- 设置较粗的 distanceFilter 值。
- 不要求过高精度。
- 正确设置 activityType 并允许更新暂停。

4.2 位置监控

位置监控由系统代劳,应用无需在后台持续运行,一般需 “Always” 授权。它比全面位置跟踪更节能,依赖基站位置估算设备位置。
- 重要提醒 :务必在不需要时调用 stopMonitoring 方法,否则会持续耗电,用户可能删除应用。
- 应用状态处理
- 应用在后台暂停 :唤醒应用接收代理事件。
- 应用未运行 :后台重新启动应用,应用代理会收到 application(_:didFinishLaunchingWithOptions:) 消息。

4.3 位置监控类型

监控类型 检查方法 启动方法 代理方法
显著位置变化监控 significantLocationChangeMonitoringAvailable startMonitoringSignificantLocationChanges locationManager(_:didUpdateLocations:)
访问监控 significantLocationChangeMonitoringAvailable startMonitoringVisits locationManager(_:didVisit:)
区域监控 isMonitoringAvailable(for:CLCircularRegion.self) startMonitoring(for:) locationManager(_:didEnterRegion:) locationManager(_:didExitRegion:) locationManager(_:monitoringDidFailFor:withError:)
地理围栏本地通知 配置 UNNotificationRequest 并设置 UNLocationNotificationTrigger

5. 设备朝向检测(Heading)

5.1 基本原理与可用性检查

对于配备磁力计的设备,Core Location 支持利用磁力计确定设备的朝向。使用磁力计报告设备相对于磁北的方向时,无需开启定位服务;但要报告真北方向,则需要开启定位服务,因为这依赖于设备的位置。

首先,需要检查所需功能是否可用,即调用 headingAvailable 方法。确认可用后,配置位置管理器并调用 startUpdatingHeading 方法开始更新设备朝向信息。此后,代理会不断收到 locationManager(_:didUpdateHeading:) 方法的调用,直到调用 stopUpdatingHeading 或出现错误调用 locationManager(_:didFailWithError:) 方法。

5.2 朝向对象属性

一个朝向对象是 CLHeading 实例,它有两个重要属性:
- magneticHeading :表示相对于磁北的方向,以度为单位(非弧度),顺时针方向。
- trueHeading :表示相对于真北的方向,同样以度为单位(非弧度),顺时针方向。若真北方向不可用,该属性值将报告为 -1。要使真北方向可用,需要在设置应用中满足以下两个条件:
- 定位服务已开启(隐私 → 定位服务)。
- 指南针校准已开启(隐私 → 定位服务 → 系统服务)。

5.3 示例代码

以下是一个将设备用作指南针的示例代码:

guard CLLocationManager.headingAvailable() else {return} // no hardware
self.locman.headingFilter = 5
self.locman.headingOrientation = .portrait
self.locman.startUpdatingHeading()

在代理方法中,将设备的朝向以大致的方位方向显示在界面的标签中:

func locationManager(_ manager: CLLocationManager,
    didUpdateHeading newHeading: CLHeading) {
        var h = newHeading.magneticHeading
        let h2 = newHeading.trueHeading // -1 if no location info
        if h2 >= 0 {
            h = h2
        }
        let cards = ["N", "NE", "E", "SE", "S", "SW", "W", "NW"]
        var dir = "N"
        for (ix, card) in cards.enumerated() {
            if h >= Double(ix * 45) && h < Double((ix + 1) * 45) {
                dir = card
                break
            }
        }
        self.lab.text = dir
}

5.4 校准对话框处理

如果希望在需要时允许系统的指南针校准对话框出现,需要实现以下代理方法并返回 true

func locationManagerShouldDisplayHeadingCalibration(_ manager: CLLocationManager) -> Bool {
    return true
}

6. 总结

Core Location 框架为开发者提供了强大而灵活的位置和朝向检测功能。通过合理使用授权状态处理、位置跟踪、单次位置获取、后台位置跟踪以及设备朝向检测等功能,可以开发出各种与位置相关的应用。

在使用这些功能时,需要注意以下几点:
- 授权处理:确保正确处理用户的授权状态,避免因授权问题导致功能无法正常使用。
- 节能优化:在满足应用需求的前提下,尽量优化定位精度、距离过滤器和自动暂停更新等设置,以节省设备电量。
- 资源管理:及时停止不必要的位置跟踪和监控,避免浪费系统资源和消耗过多电量,影响用户体验。

通过遵循这些原则,开发者可以充分利用 Core Location 框架的优势,为用户提供优质的位置相关服务。

以下是一个简单的流程图,展示了使用 Core Location 进行位置跟踪的基本流程:

graph LR
    A[检查授权状态] --> B{是否授权}
    B -- 是 --> C[配置位置管理器]
    B -- 否 --> D[请求授权]
    D --> A
    C --> E[开始位置跟踪]
    E --> F{是否需要停止跟踪}
    F -- 是 --> G[停止位置跟踪]
    F -- 否 --> E

同时,为了更清晰地对比不同的位置监控类型,这里再次给出一个表格:
| 监控类型 | 检查方法 | 启动方法 | 代理方法 |
| ---- | ---- | ---- | ---- |
| 显著位置变化监控 | significantLocationChangeMonitoringAvailable | startMonitoringSignificantLocationChanges | locationManager(_:didUpdateLocations:) |
| 访问监控 | significantLocationChangeMonitoringAvailable | startMonitoringVisits | locationManager(_:didVisit:) |
| 区域监控 | isMonitoringAvailable(for:CLCircularRegion.self) | startMonitoring(for:) | locationManager(_:didEnterRegion:) locationManager(_:didExitRegion:) locationManager(_:monitoringDidFailFor:withError:) |
| 地理围栏本地通知 | 无 | 配置 UNNotificationRequest 并设置 UNLocationNotificationTrigger | 无 |

通过以上的介绍和示例,相信开发者可以更好地理解和应用 Core Location 框架,开发出更加优秀的位置相关应用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值