Cocoa框架-Core Location

来源:互联网 发布:淘宝店铺地址在哪里看 编辑:程序博客网 时间:2024/05/18 22:17

1. 简介

Core Location 是用于帮助设备确定当前的位置、运动朝向及基于位置的距离、速度、方向等信息的 iOS 框架。参考《精通iOS框架》做了简单的总结。

2. 使用步骤

应用显示位置经过下面几个简单的步骤:

(1)位置信息授权

1.首先,在应用中使用 Core Location 框架,需要导入 Core Location,使用指令:“import”:

@import CoreLocation;

2.然后在 .plist 文件中添加一个条目,用于说明程序将会使用用户位置信息。使用到2个相关的关键字:NSLocationWhenUseUsageDescriptionNSLocationAlwaysUsageDescription 。若没有找到授权类型关键字,就不会调用该请求所允许的对话框。

Core Location 的访问服务策略有:
Always, While Using 或 Never 三种,分别对应的是允许访问设备的位置信息的三种类型。

  • Always
    表示即使在程序未激活时,用户也允许相应的程序访问位置信息。
  • While Using
    表示仅在应用处于前台且是激活状态时,允许访问设备的位置信息。
  • Never
    表示不允许访问设备的位置信息。
    前面二者使用 CLLocationManager 类,调用的函数分别为:
//1. Always:requestAlwaysAuthorization//2. When in userequestWhenInUseAuthorization
  • requestAlwaysAuthorization
    按照苹果 API 的说法:
    仅在必须后台启动位置服务时,才调用requestAlwaysAuthorization。按照苹果的隐私策略和用户对电池损耗的顾虑,必要情况下才使用此函数。 因为开启后,应用即使被手动关闭,在位置监控服务检测到位置变化等改变时,服务仍将重启。在应用处于后台时,iOS 将显示一个提示框,告知正在使用位置服务的 App 的信息。

*Calling this method will trigger a prompt to request “always”
* authorization from the user. If received, “always” authorization grants access to the user’s
* location via any CLLocationManager API, and grants access to
* launch-capable monitoring API such as geofencing/region monitoring,
* significante location visits, etc. Even if killed by the user, launch
* events triggered by monitored regions or visit patterns will cause a
* relaunch.
*
* “Always” authorization presents a significant risk to user privacy, and
* as such requesting it is discouraged unless background launch behavior
* is genuinely required. Do not call +requestAlwaysAuthorization unless
* you think users will thank you for doing so.

警告提示框
此图片来源于苹果官网,版权归苹果所有。

  • requestWhenInUseAuthorization
    “When in use” 类型的授权,从后台触发时,并不保证:激活位置,明显的地点变化和访问;startUpdatingLocation 函数也不会被触发。

“When-in-use” authorization does NOT enable monitoring API on regions,
* significant location changes, or visits, and -startUpdatingLocation will
* not succeed if invoked from the background.
调用位置服务后,应用在访问位置时,都会有弹框提示用户授权,如下图所示:
访问位置的弹框
此弹框演示了开启位置授权的请求,来源于官网
当用户点击了弹框,将触发CLLocationManagerDelegate回调函数:

- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_4_2);

通常的实现方式是:

- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {    // User has explicitly denied authorization for this application, or    // location services are disabled in Settings.    if (kCLAuthorizationStatusAuthorized == status) {        //stop updating location        NSString *errorMessage = @"Location Services Permission Denied";        NSDictionary *errorInfo = @{NSLocalizedDescriptionKey:errorMessage};        NSError *deniedError = [NSError errorWithDomain:@"ICFLocationErrorDomain"                                                   code:1 userInfo:errorInfo];        //handle error: show dialog for example.        //now add log only.        NSLog(@"location serviece was denied:%@",deniedError);    }    if (kCLAuthorizationStatusAuthorizedWhenInUse == status ||        kCLAuthorizationStatusAuthorizedAlways == status) {        //start updating location    }}

如果用户日后更改位置服务的权限,无论是更改单个应用还是更改整个设备的权限,都将触发同一个回调方法。

(2)检查服务

首先,检查设备是否开启了位置服务,可以使用 CLLocationManager 类中名为 locationServicesEnabled 的方法。
函数调用如下:

if ([CLLocationManager locationServicesEnabled]) {    //handle location} else {    // show information and     // tell the user how to open location service}

在用户没权限处理有关服务的请求时,给予用户清楚的引导,使其能够顺利开启当前位置的服务功能。

(3)发起位置请求

在位置服务授权完成后, 就可以使用 CLLocationManager 实例获得当前位置。
在实际开发使用时,可以根据需要指定精确的参数,告诉 CLLocationManager 对象在目前电量使用情况下是否需要精确的定位,或者为了节省电量而选择较低精确度的定位,使用低精确度也可减少获取位置的时间。
设置距离过滤器可以让 CLLocationManager 对象知道在新位置生成前需要遍历多远的距离,可以基于位置变化进行微调。
最后,为 CLLocationManager 对象设置委托,对于位置事件和权限情况的改变等,可以回调处理。当应用准备获取位置时,会请求位置管理器对象更新位置。

CLLocationManager *manager = [[CLLocationManager alloc] init];[manager setDesiredAccuracy:kCLLocationAccuracyBest];[manager setDistanceFilter:100.0f];[manager setDelegate:self];

可选的位置精度信息如下:

/* *  kCLLocationAccuracy<x> *   *  Discussion: *    Used to specify the accuracy level desired. The location service will try its best to achieve *    your desired accuracy. However, it is not guaranteed. To optimize *    power performance, be sure to specify an appropriate accuracy for your usage scenario (eg, *    use a large accuracy value when only a coarse location is needed). */extern const CLLocationAccuracy kCLLocationAccuracyBestForNavigation __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_4_0);extern const CLLocationAccuracy kCLLocationAccuracyBest;extern const CLLocationAccuracy kCLLocationAccuracyNearestTenMeters;extern const CLLocationAccuracy kCLLocationAccuracyHundredMeters;extern const CLLocationAccuracy kCLLocationAccuracyKilometer;extern const CLLocationAccuracy kCLLocationAccuracyThreeKilometers;

位置的更新参数可选,当达到指定的更新参数值时,位置将更新:

/* *  distanceFilter *   *  Discussion: *      Specifies the minimum update distance in meters. Client will not be notified of movements of less  *      than the stated value, unless the accuracy has improved. Pass in kCLDistanceFilterNone to be  *      notified of all movements. By default, kCLDistanceFilterNone is used. */@property(assign, nonatomic) CLLocationDistance distanceFilter;

根据参数设置情况, CLLocationManager 将选择 GPSWi-Fi, 或者同时使用这两者来确定位置。当位置管理器更新当前位置或无法更新当前位置时,需要实现这两个委托方法。

  • 成功当成功获得位置信息时,会调用 locationManager:didUpdateLocations: 方法。
- (void)locationManager:(CLLocationManager *)manager     didUpdateLocations:(nonnull NSArray<CLLocation *> *)locations {    // Get last location    CLLocation *lastLocation = [locations lastObject];    if (0 > lastLocation.horizontalAccuracy) {        return;    }    //use lastLocation}

位置传感器可以传递数组包含的多个位置信息,数组中的最后一个对象就是最近刷新的位置,位置管理器还可以在实际获取位置前快速返回最后一次 GPS 的位置信息,不过这样的话,如果 GPS 关闭并且设备此时发生位移,位置就会出错。
位置管理器会随着位置的刷新多次调用该方法,所以这里的任何逻辑处理都要注意到这一点。

  • 失败
    当没有获取位置信息时,将调用
    locationManager:didFailWithError: 方法。
    出错的可能包括:GPSWi-Fi 不可用,位置服务被关闭等。程序会通知位置管理器更新位置信息,并捕捉位置信息用来显示。
    需要补充的是:位置管理器可以对位置变化进行过滤,以拒绝对微小的变化进行处理。
CLLocationDegrees degreesFilter = 2.0;if ([CLLocationManager headingAvailable]) {    [manager setHeadingFilter:degreesFilter];    [manager startUpdatingHeading];}

运动朝向事件会通过委托:

locationManager:didUpdateHeading:

进行回调处理。

 - (void)locationManager:(CLLocationManager *)manager       didUpdateHeading:(nonnull CLHeading *)newHeading {    NSLog(@"New heading, magnetic:%f",newHeading.magneticHeading);    NSLog(@"New heading, true:%f",newHeading.trueHeading);    NSLog(@"Accuracy:%f",newHeading.headingAccuracy);    NSLog(@"Timestamp:%@",newHeading.timestamp);}

新的运动朝向包括:磁极和真实朝向,从正北方向按度的单位来表示;其提供一种正确的读法,用数字表示磁场方向的度数:正值表示更精确的朝向,负值表示朝向无效,或者存在磁场干扰无法读数。
时间戳信息会记录读数发生的时间,以避免使用之前未更新的朝向信息。

(4)解析使用

当位置管理器返回信息时,就会生成一个 CLLocation 实例。 CLLocation 实例包含许多位置相关的信息:

  • CLLocationCoordinate2D
    2维位置信息,包括经纬度。
    其中纬度使用赤道以北或以南的值表示,北纬为正值,北极为90度;南纬为负值,南极为-90度;
    经度则以本初子午线为准,向西为负,最大到 -180度,向东为正,最大值为180度。
    如果设备具有 GPS 功能,那么位置信息还会包含垂直精度信息。
  • CLLocationAccuracy
    单位为米,表示距坐标指定的范围多少米的距离。
    具有horizontalAccuracy(水平精度)和 verticalAccuracy (垂直精度)两个值。
  • CLLocationDistance
    返回精度为米的距离值。
  • CLLocationSpeed
    返回以米/秒的速度信息
  • CLLocationDirection
    返回以正北计算表示的路径信息

(5)重大变更通知

在设备发生较大位移时通知应用,这样可以很好地维持 GPSWi-Fi 检测当前位置,又能有效节省设备的电量。

[manager startMonitoringSignificantLocationChanges];

异步调用返回时,会调用delegate的回调:

locationManager:didUpdateLocations: 

位移超过500米或者换基站时会产生一条通知,上一次通知过去 5 分钟内不会重复发送通知。


3. 总结

Core Location 通过设置位置服务请求类型、编辑plist文件来开启位置服务发起位置请求回调解析位置信息,并在位置发生改变时更新。
位置信息包括经纬度速度朝向距离变化值等信息,通过委托模式,在位置发生改变时更新上述位置信息。

0 0
原创粉丝点击