地图 | 定位技术

LBS技术(Location Based Service): 基于位置的定位服务.

相关框架

  • CoreLoacation.framework
  • MapKit.framework
目标: 使用定位服务,获取用户的位置
//没有决定权限状态
 kCLAuthorizationStatusNotDetermined = 0,

//权限状态限制
 kCLAuthorizationStatusRestricted,

//拒绝状态,必须需要用户手动修改.
 kCLAuthorizationStatusDenied,

//任意时刻都需要定位
 kCLAuthorizationStatusAuthorizedAlways :

 // launch APIs has not been granted.
//当使用的时候定位
 kCLAuthorizationStatusAuthorizedWhenInUs
  1. 授权:iOS8后,需要App自己手动的调用授权相关的代码.

      1. CLLocationManager类:官方文档:定位授权的相关操作.
        1. 判断当前的授权状态
        2. 请求用户授权(前提是配置info.plsit:NSLocationWhenInUseUsageDescription(注意不带带空格,错都不知道为什么,为什么需要使用定位)
        3. 授权请求的结果,需要代理去获取.(哪个代理方法:)
    1. 代理方法,授权didChange方法
      根据status来处理,注意当用户拒绝时,需要提醒用户打开定位权限.
  2. 使用定位服务,来获取位置.

    1. 开始更新位置.
    2. 实现代理方法(两个),CLLocation类对象?
    3. 这是个数组?why,拿到设备的经纬度.
    4. 模拟器的位置是假的,可以是自己设置,有bug.
    5. 有一个updata(多次更新位置需要stop)方法,一个request方法(获取一次位置)
    6. 处理错误信息.location..fail方法是成对实现的
请求位置
[self.manager requestLocation];

// 位置更新和发生错误成对出现
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
    //   locations至少包含有一个位置 (最新的当前位置)
    // 如果是延迟模式或者是多个位置值还没有处理, 可能会包含多个位置
    CLLocation *location = locations.lastObject;
    // 获取经度和纬度coordinate坐标的意思
    CLLocationCoordinate2D coordinate = location.coordinate;
    NSLog(@"%f",coordinate.longitude);
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
    NSLog(@"位置更新错误%@",error);
}
  • 程序后台允许更新位置:注意需要配置
地图 | 定位技术_第1张图片
Snip20161025_1.png

假的跑步应用

  1. 请求位置更新
  2. 代理方法获得参数locations
  3. 根据对象location获取两个的距离和时间累加,算出速度
[self.manager startUpdatingLocation];
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
             // 获取距离
              [currentLocation distanceFromLocation:self.previousLocation];
           // 获取时间间隔
              NSTimeInterval time = [currentLocation.timestamp timeIntervalSinceDate:self.previousLocation.timestamp];
}

做指南针的应用(真机才能用,模拟器不支持)

  • 跟方向有关(heading)
  • 1, 先判断硬件是否支持
  • 2, 开启更新方向,实现代理方法
  • 3, CLHeading类,磁北偏移量属性
//开启方向更新
[self.manager startUpdatingHeading];
//代理方法
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading {
                // 磁北偏移量, (地磁场的北极)
    // 0度表示的磁场北极, 顺时针旋转递增, 0 ~ 359.9 的角度值
    CLLocationDirection direction = newHeading.magneticHeading;
}

区域监听:判断用户是否跨入边界

CLRegion:查文档,发现需要使用子类,圆形区域.

//    In iOS, you do not create instances of this class directly; instead, you instantiate 
subclasses that define specific types of regions
因此这个region对象参数需要子类获取,打开方法说明知道需要调用哪几个代理方法.
[self.manager startMonitoringForRegion:region];

地理编码和反地理编码

地理描述:经纬度,海拔(机器识别)
文字描述:位置(用户友好)

地理编码:文字->地理
反地理编码:地理->文字
本质上是网络请求,发送数据apple帮你查询.
类:CLGeoCoder:地理编码类,进行地理和反地理编码
类:CLPlacemark:既包含地理描也包含文字描述

MapKit

地图视图的使用

Xcode6.0之后,直接引用头文件会"自动"导入官方库,但是还是崩溃,是因为你没有使用它[MKMapView class]一使用就不会崩溃了.自己是直接导入了框架了.

  1. 直接使用MKMapView,会崩溃.要先导入MapKit框架(导入加引用)
  2. 部分显示地图(去哪等)必须关闭手势.(三个手势,拖拽,捏合,旋转)
  • 显示用户所在位置(需要申请授权)
    1. 申请定位授权
    2. 设置mapView显示用户所在区域.
      ** overlay **覆盖.
    _mapView.zoomEnabled = YES;
    _mapView.scrollEnabled = YES;
    _mapView.rotateEnabled = YES;
    
    _mapView.delegate = self;
#pragma mark - 代理方法
//地图区域将要改变
//- mapView:regionWillChangeAnimated:
//Tells the delegate that the region displayed by the map view is about to change.
//地图区域已经改变动画
//- mapView:regionDidChangeAnimated:
//Tells the delegate that the region displayed by the map view just changed.
//地图被加载
//- mapViewDidFinishLoadingMap:
//Tells the delegate that the specified map view successfully loaded the needed map data.

---------------------------------------------------------------------

//地图显示用户所在位置前(涉及隐私三步)
// ========== 显示用户所在的位置 ==========
    // 显示用户所在位置 (本质上是需要定位用户所在位置)
    // 一旦地图定位到用户所在位置, 会触发相关的代理方法
    [self.mapView setShowsUserLocation:YES];
显示用户大头针
/**
 地图视图已经更新了用户位置 (定位到新数据)
 @param userLocation 用户位置的"大头针"(Annotation, 注解)数据模型
 */
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
    // MKUserLocation : 专门用来表示用户位置的数据 (大头针视图的数据模型)
    // M - V (视图 - 模型)
    NSLog(@"%@", userLocation.title);
}
// 地图追踪模式
self.mapView.userTrackingMode = MKUserTrackingModeFollow;

自定义大头针.

MKAnnotation注释协议,自定义类类,遵守协议.

  1. 写三个协议内的属性.

MKAnnotationView地图注释View,就是大头针.

创建MKAnnotationView的子类
目标:希望继承这个类的MKAnnotation属性内的三个属性,并且还能新增功能属性.
1. 写一个同名属性
将@property (nonatomic, strong, nullable) id  annotation;换成下面的属性
@property (nonatomic, strong, nullable) ZLAnnotation * annotation;
这样会产生警告
2. 跟父类的相同属性,变为自己的解决办法:先写个同名属性,但是不要生成setter和getter方法,加关键字,就不会报警告了.
@dynamic annotation;
3. 重写setter方法
#pragma mark - 重写setter方法
- (void)setAnnotation:(ZLAnnotation *)annotation {
    //Annotation是从父类继承过来的属性
    // 父类的setAnnotation会处理coordinate, title, 和subtitle这三个属性.就有了标题等内容
#pragma mark - 关键,先把父类的属性赋值过来,在实现自己需要实现的功能.
    super.annotation = annotation;
    
    //再来处理自己有关的操作
    NSString *imageName = [NSString stringWithFormat:@"category_%zd",annotation.type + 1];
    self.image = [UIImage imageNamed:imageName];
}

路线规划

路线规划的本质是向地图上添加遮盖.
V-M的视图设计模式(先获取系统的原型model),在通过代理 获取视图对象.
大头针和路线遮盖都是这样的原理.

集成百度地图SDK的应用

配置:根据百度官方API介绍配置,不要遗漏就可以了.

目标:导入百度地图进行使用.

  1. 注册
  2. 简介和配置秘钥
  3. 重点看注意事项:
    1. 注意地图视图的生命周期
    2. 配置info.plist文件
      下载SDK,以前是一个库.a文件,现在是多个.framework.方便了,只要导入相关的framework.(查阅百度官方解释)
      注意:先不导,然后根据错误来导入.
  4. 添加相关framework
  5. 导入相关boundle(其实就是文件),内有资源
  6. 导入百度地图引用的系统框架.
  7. 解决object-C+=的问题.
    1. 修改某个文件的后缀为.mm (why?系统编译是根据文件类型来支持语言.mm就可以也支持ocject-C++了)
    2. 设置buildSetting.搜索compile source as,设置为object-C
  8. 解决boundle display name问题.表示项目名称.
  9. 加载BMKmapView,得到地图视图.注意额外注意生命周期问题.

注意真实项目中,所有的第三方SDK需要用单独的.h文件管理.永发哦了导入,不用pch文件.

  • 代码:
    1. 初始化BMKMapManager,启动百度地图
    2. 使用百度地图.

https:在iOS9之后,苹果需要采用的安全传输协议https,需要配置的.
.framework是什么:库,框架.Xcode6以后推出的framework

  1. 百度地图的生命周期和代理设置的问题

Overlay遮盖.
ParkMark商圈标记点

目标:百度地图的定位功能

  1. 开始定位
    1. 百度地图的定位和地图功能是分开的.所以需要重新导入新的BMKLocation.framework.
    2. 核心类:BMKLocationService定位服务
    3. 类比原生:创建对象,设置代理返回数据.
    4. 开始定位(方法介绍,需要配置info.plist)
  2. 用户的位置数据模型
    1. 代理方法中BMKUserLocation参数:用户当前位置的大头针数据模型
    2. 错误处理:查找相关错误code,在BMKTypes.h文件中,查找
    3. 相关属性:desiredAccuary精确度.看官方解释
  3. 地图显示用户位置(搜mapView库location)
    1. 显示用户所在位置.
    2. 将用户数据传给地图,更新位置数据
      结果:能显示位置,但是不会跳转到用户位置
  4. 设置地图显示区域
  5. 手动设置用户所在区域.
  6. setRegion方法,根据参数写位置.
  7. 导入工具模块.BMKUtils
  8. 获取用户的位置(便利操作:LocationService有更新位置的属性,定位后才是正确的)
  9. 追踪用户位置.
  10. 开启用户追踪模式
  11. 周期兴趣点查询(POI - ponit of interset)
    POI:ATM,KTV,电影院等等
    1. 导入searchAPI,有关的查找功能
    2. BMKPoiSearch类.
    3. 设置代理,需要在viewWillAppear配置和代理置空问题,否则影响释放.
    4. poiSearchNearBy方法参数option配置(很多需要配置,注意看一下,关键字等).
    5. 代理方法回调结果:查一下
    6. poiResult获取poiInfo类
  12. 大头针添加(mapView)
    1. 1.添加一个大头针数据,使用系统提供的表示一个点的大头针(找一下),不用自定义
      2.根据你遍历模型数据,指定大头针.
  13. 自定义大头针视图
    1. mapView的代理方法,返回某个模型对应的视图
    2. 判断类型BMKPointAnnotation返回对应的视图(类比原生)
    3. 创建BWKPinAnnotationView注意复用问题.
    4. 配置模型
  14. 需要改默认我的位置图片,但是不知道类型,代码改不了.
    可以进入百度素材,改百度素材里面的图片名,并且注意同名.

新的东西:实现点击大头针触发弹出自定义窗口

  1. 百度的paopaoView.相似原生的自定义BMKAnnotationView.
  2. 有一个在这里上车的绿标大头针,他一直显示在屏幕的正中央.怎么做的?
    1. 把绿标不加载mapView上,而是加在view上.
    2. 获取绿标所在位置的经纬度描述.地图mapView提供了很多frame和坐标进行转化的方法.
      // 转换坐标点
      convertPoint方法返回一个坐标点.
      
    3. 利用反地理编码,获取详细信息.在search框架内.
  3. 周边标志性地表查找
    1. 通过反地理编码可以获取到周边的标志性地标.
    2. 反地理编码的poiList属性,就可以获取到周边信息了.

你可能感兴趣的:(地图 | 定位技术)