iOS10地图定位 适配各版本

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;
        }
            /*获得前台定位授权*/
        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];
        }
    }];

猜你喜欢

转载自blog.csdn.net/ios_qing/article/details/52966922