标签:
地图与定位(LBS)-CoreLocation篇
一:地图与定位基本框架(MapKit时基于CoreLocation实现的夜可以实现定位)
二:开发常用技术
- LBS:基于位置的服务
- SoLoMo:社交,本地,移动化
三:定位授权提示(iOS之前)
四:每个一段距离定位
五:后台服务:默认只能在前台服务
plist文件中
对应plist文件的值(数组)
六:基于基站定位
七:iOS8以上的服务
定位服务开启
开启授权
后台服务(可以不勾选后台模式)
开启后台授权
授权改变
// 如果授权状态发生变化时,调用
// status : 当前的授权状态
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
switch (status) {
case kCLAuthorizationStatusNotDetermined:
{
NSLog(@"用户未决定");
break;
}
case kCLAuthorizationStatusRestricted:
{
NSLog(@"受限制");
break;
}
case kCLAuthorizationStatusDenied:
{
// 判断当前设备是否支持定位, 并且定位服务是否开启()
if([CLLocationManager locationServicesEnabled])
{
NSLog(@"定位开启,被拒绝");
// ios8,0- 需要截图提醒引导用户
// iOS8.0+
NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
if([[UIApplication sharedApplication] canOpenURL:url])
{
[[UIApplication sharedApplication] openURL:url];
}
}else
{
NSLog(@"定位服务关闭");
}
break;
}
case kCLAuthorizationStatusAuthorizedAlways:
{
NSLog(@"前后台定位授权");
break;
}
case kCLAuthorizationStatusAuthorizedWhenInUse:
{
NSLog(@"前台定位授权");
break;
}
default:
break;
}
}
八:系统适配
1:根据系统的版本
2:根据方法的响应
3:iOS9中版本判断
九:提示用户开启定位
- iOS8之后:跳转URL

十:关于iOS9定位
后台定位需要增加一个属性(在勾选后台活着增加plist属性之后)
iOS9中请求一次定位信息
十一:id加范型->is Kind of
判断当前位置是否可用
或者
十二:指南针
在创建管理者设置代理
// 获取当前设备朝向
[self.locationM startUpdatingHeading];
然后在代理方法中实现下面的代码
// 已经更新到用户设备朝向时调用
-(void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
{
// magneticHeading : 距离磁北方向的角度
// trueHeading : 真北
// headingAccuracy : 如果是负数,代表当前设备朝向不可用
if (newHeading.headingAccuracy < 0) {
return;
}
// 角度
CLLocationDirection angle = newHeading.magneticHeading;
// 角度-> 弧度
double radius = angle / 180.0 * M_PI;
// 反向旋转图片(弧度)
[UIView animateWithDuration:0.5 animations:^{
self.compassView.transform = CGAffineTransformMakeRotation(-radius);
}];
}
十三:区域监听
判断区域类
判断区域大小
区域变化
十四:监听区域的时候调用的代理方法
1.进入
/**
* 进入区域调用(是一个动作)
*
* @param manager 位置管理者
* @param region 区域
*/
-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
NSLog(@"进入区域");
self.noticeLabel.text = @"小码哥欢迎你, 给你技术";
}
2.离开
/**
* 离开某个区域调用
*
* @param manager 位置管理者
* @param region 区域
*/
-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
{
NSLog(@"离开区域");
self.noticeLabel.text = @"祝大神三期找到30K";
}
3.判断和区域的位置对应
/**
* 请求某个区域的状态是调用
*
* @param manager 位置管理者
* @param state 状态
* @param region 区域
*/
-(void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region
{
// CLRegionStateUnknown, 未知状态
// CLRegionStateInside, // 在区域内部
// CLRegionStateOutside // 区域外面
if(state == CLRegionStateInside)
{
self.noticeLabel.text = @"小码哥欢迎你, 给你技术";
}else if (state == CLRegionStateOutside)
{
self.noticeLabel.text = @"祝大神三期找到30K";
}
}
4.失败
/**
* 监听区域失败时调用
*
* @param manager 位置管理者
* @param region 区域
* @param error 错误
*/
-(void)locationManager:(CLLocationManager *)manager monitoringDidFailForRegion:(CLRegion *)region withError:(NSError *)error
{
// 经验: 一般在这里, 做移除最远的区域
// [manager stopMonitoringForRegion:最远区域]
}
十五:编码与反编码
地理编码:位置名称->经纬度
NSString *address = self.addressTV.text;
// 容错
if([address length] == 0)
return;
[self.geoC geocodeAddressString:address completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
// CLPlacemark : 地标
// location : 位置对象
// addressDictionary : 地址字典
// name : 地址详情
// locality : 城市
if(error == nil)
{
CLPlacemark *pl = [placemarks firstObject];
self.addressTV.text = pl.name;
self.latitudeTF.text = @(pl.location.coordinate.latitude).stringValue;
self.longitudeTF.text = @(pl.location.coordinate.longitude).stringValue;
}else
{
NSLog(@"错误");
}
}];
反地理编码:经纬度->位置名称
// 获取用户输入的经纬度
double latitude = [self.latitudeTF.text doubleValue];
double longitude = [self.longitudeTF.text doubleValue];
CLLocation *location = [[CLLocation alloc] initWithLatitude:latitude longitude:longitude];
// 反地理编码(经纬度---地址)
[self.geoC reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
if(error == nil)
{
CLPlacemark *pl = [placemarks firstObject];
self.addressTV.text = pl.name;
self.latitudeTF.text = @(pl.location.coordinate.latitude).stringValue;
self.longitudeTF.text = @(pl.location.coordinate.longitude).stringValue;
}else
{
NSLog(@"错误");
}
}];
注:double快速转string
十六:第三方->LocationManager
基本使用
INTULocationManager *locMgr = [INTULocationManager sharedInstance];
// delayUntilAuthorized 超时计时从什么时候开始
INTULocationRequestID requestID = [locMgr requestLocationWithDesiredAccuracy:INTULocationAccuracyCity
timeout:3.0
delayUntilAuthorized:NO
block:^(CLLocation *currentLocation, INTULocationAccuracy achievedAccuracy, INTULocationStatus status) {
if (status == INTULocationStatusSuccess) {
NSLog(@"---%@", currentLocation);
}else
{
NSLog(@"错误 %zd", status);
}
}];
// 会执行block内容
// [[INTULocationManager sharedInstance] forceCompleteLocationRequest:requestID];
// 取消位置请求
[[INTULocationManager sharedInstance] cancelLocationRequest:requestID];
在使用的时候爆了一个错误
解决办法:
十七:经典实战,将代理转Blcok
定义一个Block
typedef void(^ResultBlock)(CLLocation *location, CLPlacemark *pl, NSString *error);
声明一个带Block方法
- (void)getCurrentLocation:(ResultBlock)block;
实现方法
- (void)getCurrentLocation:(ResultBlock)block
{
// 记录代码块
self.block = block;
// 获取用户位置信息
if([CLLocationManager locationServicesEnabled])
{
[self.locationM startUpdatingLocation];
}else
{
self.block(nil, nil, @"定位服务未开启");
}
}
在创建位置管理者的时候实现项目内部文件对应属性值的判断,根据不同的值提示开发者
if (!_locationM) {
_locationM = [[CLLocationManager alloc] init];
_locationM.delegate = self;
// iOS8.0之后, 必须手动请求定位授权
// 获取info.plist 里面的键值对
NSDictionary *infoDic = [NSBundle mainBundle].infoDictionary;
// NSLog(@"%@", infoDic);
if (isIOS(8.0)) {
// [_locationM requestAlwaysAuthorization];
// [_locationM requestWhenInUseAuthorization];
// 获取前后台定位描述(看其他开发者到底有没有添加这个key)
NSString *alwaysStr = infoDic[@"NSLocationAlwaysUsageDescription"];
// 获取前后台定位描述(看其他开发者到底有没有添加这个key)
NSString *whenInUseStr = infoDic[@"NSLocationWhenInUseUsageDescription"];
// 判断其它开发者, 到底填写的是哪个key
if([alwaysStr length] > 0)
{
[_locationM requestAlwaysAuthorization];
}
else if ([whenInUseStr length] > 0)
{
[_locationM requestWhenInUseAuthorization];
// 如果请求的是前台定位授权, 如果想要在后台获取用户位置, 提醒其他开发者, 勾选后台模式location updates
NSArray *backModes = infoDic[@"UIBackgroundModes"];
if (![backModes containsObject:@"location"]) {
NSLog(@"当前授权模式是前台定位授权, 如果想要在后台获取位置, 需要勾选后台模式location updates");
}else // 代表当前勾选后台模式, 而且是前台定位授权
{
if(isIOS(9.0))
{
_locationM.allowsBackgroundLocationUpdates = YES;
}
}
}else
{
NSLog(@"如果在iOS8.0之后获取用户位置, 必须主动填写info.plist文件中的key NSLocationAlwaysUsageDescription 或者 NSLocationWhenInUseUsageDescription");
}
}else // ios8.0之前
{
// 如果请求的是前台定位授权, 如果想要在后台获取用户位置, 提醒其他开发者, 勾选后台模式location updates
NSArray *backModes = infoDic[@"UIBackgroundModes"];
if (![backModes containsObject:@"location"]) {
NSLog(@"当前授权模式, 如果想要在后台获取位置, 需要勾选后台模式location updates");
}
}
}
return _locationM;
实现位置更新方法
#pragma mark -CLLocationManagerDelegate
/**
* 定位到之后调用
*
* @param manager 位置管理者
* @param locations 位置数组
*/
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
CLLocation *location = [locations lastObject];
// 判断位置是否可用
if (location.horizontalAccuracy >= 0) {
[self.geoC reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
if (error == nil) {
CLPlacemark *pl = [placemarks firstObject];
self.block(location, pl, nil);
}else
{
self.block(location, nil, @"反地理编码失败");
}
}];
}
// 如果只需要获取一次位置, 那么在此处停止获取用户位置
[manager stopUpdatingLocation];
}
实现授权改变
/**
* 当前授权状态发生改变时调用
*
* @param manager 位置管理者
* @param status 状态
*/
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
switch (status) {
// 用户还未决定
case kCLAuthorizationStatusNotDetermined:
{
NSLog(@"用户还未决定");
break;
}
// 问受限
case kCLAuthorizationStatusRestricted:
{
NSLog(@"访问受限");
self.block(nil, nil, @"访问受限");
break;
}
// 定位关闭时和对此APP授权为never时调用
case kCLAuthorizationStatusDenied:
{
// 定位是否可用(是否支持定位或者定位是否开启)
if([CLLocationManager locationServicesEnabled])
{
NSLog(@"定位开启,但被拒");
self.block(nil, nil, @"被拒绝");
}else
{
NSLog(@"定位关闭,不可用");
self.block(nil, nil, @"定位关闭,不可用");
}
break;
}
// 获取前后台定位授权
case kCLAuthorizationStatusAuthorizedAlways:
// case kCLAuthorizationStatusAuthorized: // 失效,不建议使用
{
NSLog(@"获取前后台定位授权");
break;
}
// 获得前台定位授权
case kCLAuthorizationStatusAuthorizedWhenInUse:
{
NSLog(@"获得前台定位授权");
break;
}
default:
break;
}
}
总结
开发经验
- 1:start开启服务,stop停止服务
- 2:用户隐私提示说明(交给产品经理)
- 3:重大位置-基站
关于地图术语:
1.方位简写
3.术语
- coordinate:经纬度
- altitude:海拔高度
- course航向
- distanceFromLocation。计算距离
4.返回数值
5.指南针方向
- megneticHeading:磁北
- tureHeading:真北
- headingAcceracy:负则不可用
使用总结
- 地图简单总

- 转弧

Xcode模拟器安装
解压
解压后放倒对应的路径中
iOS开发——开发实战总结OC篇&地图与定位(LBS)-CoreLocation篇
标签:
原文地址:http://www.cnblogs.com/iCocos/p/4833251.html