您的位置:首页 > 移动开发 > IOS开发

iOS10地图定位 适配各版本

2016-10-29 21:49 183 查看

CoreLocation框架

CLLocationManager对象

CLLocationManager: 位置管理者,负责对定位进行相关设置

导入头文件



distanceFilter: 设置定位距离过滤参数- 以()为单位

当上次定位和本次定位之间的距离 >= 此值时,才会调用代理通知开发者

desiredAccuracy: 设置定位精度,是个枚举类型

精确度越高,越耗电,所以需要我们根据实际情况,设定对应的精度

/** desiredAccuracy */
// 最适合导航
kCLLocationAccuracyBestForNavigation
// 最好的
kCLLocationAccuracyBest;
// 10m
kCLLocationAccuracyNearestTenMeters;
// 100m
kCLLocationAccuracyHundredMeters;
// 1000m
kCLLocationAccuracyKilometer;
// 3000m  适用定位城市
kCLLocationAccuracyThreeKilometers;


开始更新用户位置

- (void)startUpdatingLocation;


当调用了startUpdatingLocation方法后,就开始不断地请求、刷新用户的位置,一旦请求到用户位置就会调用代理的下面方法

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations;


停止更新用户位置

- (void) stopUpdatingLocation;


CLLocationManager有个类方法可以判断当前应用的定位功能是否可用

+ (BOOL)locationServicesEnabled;


iOS各个版本适配

iOS8之前版本

iOS 6开始
,苹果在保护用户隐私方面做了很大的加强,以下操作都必须经过用户批准授权

要想获得用户的
位置、通讯录、日历、相机、相册等等

当想访问用户的隐私信息时,系统会
自动弹出
一个对话框让用户授权



iOS8版本

iOS 8.0
开始,苹果进一步加强了对用户隐私的保护。

当APP想访问用户的隐私信息时,系统
不再自动弹出
一个对话框让用户授权

解决方案:

调用iOS 8.0的API,主动请求用户授权

/* 请求允许在前后台都能获取用户位置的授权 /

- (void)requestAlwaysAuthorization


/* 请求允许在前台获取用户位置的授权 /

- (void)requestWhenInUseAuthorization


务必在
info.plist文件
中配置对应的键值, 否则以上请求授权的方法不生效

NSLocationAlwaysUsageDescription
: 允许在前后台获取GPS的描述

NSLocationWhenInUseDescription
: 允许在前台获取GPS的描述

iOS9版本

iOS 9.0 如果当前处于前台授权状态,默认是不可以后台获取用户位置。但可以设置以下属性为YES,就可以继续获取后台位置,但是会出现蓝条

使用注意:必须设置对应的后台模式:location updates

- BOOL allowsBackgroundLocationUpdates


iOS 9.0 可以单次请求用户位置

//请求用户位置
- (void)requestLocation
// 成功调用
-(void)locationManager:(nonnull CLLocationManager *)manager didUpdateLocations:(nonnull NSArray<CLLocation *> *)locations
// 失败调用
-(void)locationManager:(nonnull CLLocationManager *)manager didFailWithError:(nonnull NSError *)error


附图:各版本info.plist添加版本适配key值



CLLocationManagerDelegate代理方法

/******CLLocationManagerDelegate代理方法******/
/**
更新到位置之后调用
@param manager   位置管理者
@param locations 位置数组
*/
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
NSLog(@"定位到了");

}
/**
*  授权状态发生改变时调用
*
*  @param manager 位置管理者
*  @param status  状态
*/
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
switch (status) {
/*用户还未决定*/
case kCLAuthorizationStatusNotDetermined:
{
NSLog(@"用户还未决定");
break;
}
/*问受限(很少遇到此状态)*/
case kCLAuthorizationStatusRestricted:
{
NSLog(@"访问受限");
break;
}
/*定位关闭时和对此APP授权为never时调用*/
case kCLAuthorizationStatusDenied:
{
// 定位是否可用(是否支持定位或者定位是否开启)
if([CLLocationManager locationServicesEnabled])
{
NSLog(@"定位开启,但被拒");
}else
{
NSLog(@"定位关闭,不可用");
}
break;
}
/*获取前后台定位授权*/
case kCLAuthorizationStatusAuthorizedAlways:
{
NSLog(@"获取前后台定位授权");
break;

eeec
}
/*获得前台定位授权*/
case kCLAuthorizationStatusAuthorizedWhenInUse:
{
NSLog(@"获得前台定位授权");
break;
}
default:
break;
}
}


经纬度知识普及





模拟器定位位置查找



CLLocation常用属性

CLLocationCoordinate2D coordinate: 是一个用来表示经纬度的结构体

@property(readonly, nonatomic) CLLocationCoordinate2D coordinate;
//一般用CLLocationCoordinate2DMake函数来创建CLLocationCoordinate2D
typedef struct {
CLLocationDegrees latitude; // 纬度
CLLocationDegrees longitude; // 经度
} CLLocationCoordinate2D;


CLLocationDistance altitude: 海拔

@property(readonly, nonatomic) CLLocationDistance altitude;


CLLocationDirection course: 航向

// 取值范围:0.0 - 359.9度,0度是正北
@property(readonly, nonatomic) CLLocationDirection course


CLLocationSpeed speed: 速度

// 单位:米/秒
@property(readonly, nonatomic) CLLocationSpeed speed


distanceFromLocation: 比较两点之间的距离

- (CLLocationDistance)distanceFromLocation:(const CLLocation *)location


指南针相关

headingFilter: 每隔多少度更新一次

@property(assign, nonatomic) CLLocationDegrees headingFilter


startUpdatingHeading: 监听设备朝向

- (void)startUpdatingHeading


didUpdateHeading 代理方法



磁北与真北区别:真北和磁北.jpg



CLCircularRegion区域监听

监听创建与设置

// 区域监听
// 中心点     : 结构体
// radius    : 半径
// identifier: 标识
CLLocationCoordinate2D center = {10.123, 123.456};
CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:center radius:1000 identifier:@"LXR"];

//开始监听
[self.lM startMonitoringForRegion:region];

// 请求区域状态
[self.lM requestStateForRegion:region];


监听返回结果->通过代理



MapKit框架

简介

在移动互联网时代,移动app能解决用户的很多生活琐事,比如

周边:找餐馆、找KTV、找电影院等等

导航:根据用户设定的起点和终点,进行路线规划,并指引用户如何到达

在上述应用中,都用到了定位和地图功能,在iOS开发中,要想加入这2大功能,必须基于2个框架进行开发

CoreLocation:用于地理定位,地理编码,区域监听等(着重功能实现)

MapKit:用于地图展示,例如大头针,路线、覆盖层展示等(着重界面展示)

MapKit框架的使用

MapKit框架使用前提

导入框架(Xcode5之后可以省略,前提:在代码里面使用了框架中某个类创建了一个对象)



导入主头文件



MapKit框架使用须知

MapKit框架中所有数据类型的前缀都是MK

MapKit有一个比较重要的UI控件 :MKMapView,专门用于地图显示



MKMapView控件

mapType地图的类型



其他属性



设置MKMapView的showsUserLocation属性可以显示用户的当前位置



MKMapView地图显示



MKCoordinateRegion属性



MKMapView代理



MKUserLocation(代理方法中参数)



大头针

大头针的基本使用



大头针的基本操作



大头针模型



添加大头针

//添加大头针
MJTuangouAnnotation *anno = [[MJTuangouAnnotation alloc] init];
anno.title = @"标题";
anno.subtitle = @"副标题";
anno.coordinate = CLLocationCoordinate2DMake(纬度, 经度);
[self.mapView addAnnotation:anno];


自定义大头针





实例代码

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
// 判断annotation的类型
if (![annotation isKindOfClass:[MJTuangouAnnotation class]]) return nil;

// 创建MKAnnotationView
static NSString *ID = @"tuangou";
MKAnnotationView *annoView = [mapView dequeueReusableAnnotationViewWithIdentifier:ID];
if (annoView == nil) {
annoView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:ID];
annoView.canShowCallout = YES;
}
// 传递模型数据
annoView.annotation = annotation;

// 设置图片
MJTuangouAnnotation *tuangouAnnotation = annotation;
annoView.image = [UIImage imageNamed:tuangouAnnotation.icon];

return annoView;
}


MKAnnotationView大头针视图





MKPinAnnotationView(MKAnnotationView的子类)



利用系统App导航/数字版街景/地图快照截图

MKMapItem调用系统APP进行导航



实例代码

// 根据两个地标对象进行调用系统导航
- (void)beginNavWithBeginPlacemark:(CLPlacemark *)beginPlacemark andEndPlacemark:(CLPlacemark *)endPlacemark
{
// 创建起点:根据 CLPlacemark 地标对象创建 MKPlacemark 地标对象
MKPlacemark *itemP1 = [[MKPlacemark alloc] initWithPlacemark:beginPlacemark];
MKMapItem *item1 = [[MKMapItem alloc] initWithPlacemark:itemP1];

// 创建终点:根据 CLPlacemark 地标对象创建 MKPlacemark 地标对象
MKPlacemark *itemP2 = [[MKPlacemark alloc] initWithPlacemark:endPlacemark];
MKMapItem *item2 = [[MKMapItem alloc] initWithPlacemark:itemP2];

NSDictionary *launchDic = @{
// 设置导航模式参数
MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeDriving,
// 设置地图类型
MKLaunchOptionsMapTypeKey : @(MKMapTypeHybridFlyover),
// 设置是否显示交通
MKLaunchOptionsShowsTrafficKey : @(YES),

};
// 根据 MKMapItem 数组 和 启动参数字典 来调用系统地图进行导航
[MKMapItem openMapsWithItems:@[item1, item2] launchOptions:launchDic];
}


MKMapCamera地图街景



示例代码

// 创建视角中心坐标
CLLocationCoordinate2D center = CLLocationCoordinate2DMake(23.132931, 113.375924);
// 创建3D视角
MKMapCamera *camera = [MKMapCamera cameraLookingAtCenterCoordinate:center fromEyeCoordinate:CLLocationCoordinate2DMake(center.latitude + 0.001, center.longitude + 0.001) eyeAltitude:1];
// 设置到地图上显示
self.mapView.camera = camera;


MKMapSnapshotter地图截图



示例代码

// 截图附加选项
MKMapSnapshotOptions *options = [[MKMapSnapshotOptions alloc] init];
// 设置截图区域(在地图上的区域,作用在地图)
options.region = self.mapView.region;
options.mapRect = self.mapView.visibleMapRect;

// 设置截图后的图片大小(作用在输出图像)
options.size = self.mapView.frame.size;
// 设置截图后的图片比例(默认是屏幕比例, 作用在输出图像)
options.scale = [[UIScreen mainScreen] scale];

MKMapSnapshotter *snapshotter = [[MKMapSnapshotter alloc] initWithOptions:options];
[snapshotter startWithCompletionHandler:^(MKMapSnapshot * _Nullable snapshot, NSError * _Nullable error) {
if (error) {
NSLog(@"截图错误:%@",error.localizedDescription);
}else
{
// 设置屏幕上图片显示
self.snapshootImageView.image = snapshot.image;
// 将图片保存到指定路径(此处是桌面路径,需要根据个人电脑不同进行修改)
NSData *data = UIImagePNGRepresentation(snapshot.image);
[data writeToFile:@"/Users/wangshunzi/Desktop/snap.png" atomically:YES];
}
}];
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息