corelocation

“人之贤不肖譬如鼠矣,在所自处耳。”——《史记·李斯列传》

术语:

LBS: Location Based Service
SoloMo: Social Local Mobile (索罗门)

结构:

应用:

获取用户位置信息:

更改模拟器位置信息Debug->Location->Custom Location
从iOS6.0之后,启动用户隐私(照片,通讯录等)服务,需要用户授权.

iOS8.0之前:
系统自动弹框,让用户进行授权.更改弹框文案需配置info.plist->Privacy - Location Usage Description

1
2
3
4
5
CLLocationManager *locationM = [[CLLocationManager alloc] init];
[locationM startUpdatingLocation];
// 显著位置变化的服务(基站进行定位,电话模块)
// [locationM startMonitoringSignificantLocationChanges];

定位完成后更新位置信息会调用CLLocationManagerDelegate代理方法:

1
2
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
}

后台定位需要配置TARGETS->Capabilities->Background Modes->Location updates

iOS8.0之后:
系统不会自动弹框,需要主动请求授权.首先配置info.plist:NSLocationWhenInUseUsageDescription. 此时iPhone设置中会增加While Using the App选项.并增加代码:

1
[locationM requestWhenInUseAuthorization];

后台定位有两种方案.
方案一:在上述前台定位的基础上开启后台定位 TARGETS->Capabilities->Background Modes->Location updates.这种方案退出后台后,屏幕上方会有蓝色提示.
方案二:首先配置info.plist:NSLocationAlwaysUsageDescription. 此时iPhone设置中会增加Always选项. 并增加代码:

1
[locationM requestAlwaysAuthorization];

iOS9.0之后:
增加[locationM requestLocation],定位方式是精确度从低到高依次定位,如果定位超时,定位到当前位置.不能与startUpdatingLocation同时使用,并且必须实现locationManager didFailWithError代理方法.
后台定位只有上述”iOS8.0后台定位方案一”略有改变,需要将allowsBackgroundLocationUpdates属性设置为YES.

1
locationM.allowsBackgroundLocationUpdates = YES;

监听授权:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 授权状态发生改变时调用
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
switch (status) {
case kCLAuthorizationStatusNotDetermined:
NSLog(@"用户没有决定");
break;
case kCLAuthorizationStatusRestricted:
NSLog(@"受限制");
break;
case kCLAuthorizationStatusDenied:
NSLog(@"拒绝");
if ([CLLocationManager locationServicesEnabled]) {
NSLog(@"真正被拒绝");
// 8.0之前截图引导用户开启
// 8.0之后直接代码跳转设置页面
NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
if ([[UIApplication sharedApplication] canOpenURL:url]) {
[[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil];
}
} else {
// 定位服务关闭状态,系统自动弹出窗口,快捷跳转到设置界面
NSLog(@"定位服务关闭");
}
break;
case kCLAuthorizationStatusAuthorizedAlways:
NSLog(@"前后台定位授权");
break;
case kCLAuthorizationStatusAuthorizedWhenInUse:
NSLog(@"前台定位授权");
break;
default:
break;
}
}

更新定位频率:

1
2
3
4
5
6
// 获取一次位置信息
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
[manager stopUpdatingLocation];
}
// 每隔100m更新位置信息一次
locationM.distanceFilter = 100;

定位精确度:

1
2
3
4
5
6
7
8
9
// 定位精确度
// kCLLocationAccuracyBestForNavigation // 最适合导航
// kCLLocationAccuracyBest // 最好的
// kCLLocationAccuracyNearestTenMeters // 附近10m
// kCLLocationAccuracyHundredMeters // 附近100m
// kCLLocationAccuracyKilometer // 附近1000m
// kCLLocationAccuracyThreeKilometers // 附近3000m
// 定位精确度越高,越耗电,定位时间越长
locationM.desiredAccuracy = kCLLocationAccuracyBestForNavigation;

磁力计:

1
2
3
4
5
CLLocationManager *locationM = [[CLLocationManager alloc] init];
// 判断当前磁力设备是否可用
if ([CLLocationManager headingAvailable]) {
[locationM startUpdatingLocation];
}

设备方向改变会调用CLLocationManagerDelegate代理方法:

1
2
3
4
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading {
//当前设备朝向
CLLocationDirection angle = newHeading.magneticHeading;
}

区域监听:

如果想要进行区域监听,在iOS8之后必须要请求用户位置授权.(参考上文).

判断当前设备能否监听某个区域:

1
BOOL isMonitor = [CLLocationManager isMonitoringAvailableForClass:[CLCircularRegion class]];

创建区域:

1
2
3
4
5
6
CLLocationCoordinate2D center = CLLocationCoordinate2DMake(21.123, 121.345);
CLLocationDistance distance = 1000;
if (distance > locationM.maximumRegionMonitoringDistance) {
distance = locationM.maximumRegionMonitoringDistance;
}
CLCircularRegion *regin = [[CLCircularRegion alloc] initWithCenter:center radius:distance identifier:@""];

监听区域:

1
2
CLLocationManager *locationM = [[CLLocationManager alloc] init];
[locationM startMonitoringForRegion:regin];

位置改变后会调用CLLocationManagerDelegate代理方法:

1
2
3
4
5
6
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region {
NSLog(@"进入区域调用");
}
- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region {
NSLog(@"离开区域调用");
}

请求某个区域状态:

1
[locationM requestStateForRegion:regin];

请求成功后会调用CLLocationManagerDelegate代理方法:

1
2
-(void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region {
}

本文作者: WalkerZ

本文链接: https://walkerzhan.github.io/2017/07/17/CoreLocation/

版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!