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;
- 当调用了startUpdatingLocation方法后,就开始不断地请求、刷新用户的位置,一旦请求到用户位置就会调用代理的下面方法
停止更新用户位置
- (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;
}
/*获得前台定位授权*/
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];
}
}];