LBS技术(Location Based Service): 基于位置的定位服务.
相关框架
- CoreLoacation.framework
- MapKit.framework
目标: 使用定位服务,获取用户的位置
//没有决定权限状态
kCLAuthorizationStatusNotDetermined = 0,
//权限状态限制
kCLAuthorizationStatusRestricted,
//拒绝状态,必须需要用户手动修改.
kCLAuthorizationStatusDenied,
//任意时刻都需要定位
kCLAuthorizationStatusAuthorizedAlways :
// launch APIs has not been granted.
//当使用的时候定位
kCLAuthorizationStatusAuthorizedWhenInUs
-
授权:iOS8后,需要App自己手动的调用授权相关的代码.
- CLLocationManager类:官方文档:定位授权的相关操作.
- 判断当前的授权状态
- 请求用户授权(前提是配置info.plsit:NSLocationWhenInUseUsageDescription(注意不带带空格,错都不知道为什么,为什么需要使用定位)
- 授权请求的结果,需要代理去获取.(哪个代理方法:)
- CLLocationManager类:官方文档:定位授权的相关操作.
- 代理方法,授权didChange方法
根据status来处理,注意当用户拒绝时,需要提醒用户打开定位权限.
-
使用定位服务,来获取位置.
- 开始更新位置.
- 实现代理方法(两个),CLLocation类对象?
- 这是个数组?why,拿到设备的经纬度.
- 模拟器的位置是假的,可以是自己设置,有bug.
- 有一个updata(多次更新位置需要stop)方法,一个request方法(获取一次位置)
- 处理错误信息.location..fail方法是成对实现的
请求位置
[self.manager requestLocation];
// 位置更新和发生错误成对出现
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
// locations至少包含有一个位置 (最新的当前位置)
// 如果是延迟模式或者是多个位置值还没有处理, 可能会包含多个位置
CLLocation *location = locations.lastObject;
// 获取经度和纬度coordinate坐标的意思
CLLocationCoordinate2D coordinate = location.coordinate;
NSLog(@"%f",coordinate.longitude);
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
NSLog(@"位置更新错误%@",error);
}
- 程序后台允许更新位置:注意需要配置
假的跑步应用
- 请求位置更新
- 代理方法获得参数locations
- 根据对象location获取两个的距离和时间累加,算出速度
[self.manager startUpdatingLocation];
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)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]一使用就不会崩溃了.自己是直接导入了框架了.
- 直接使用MKMapView,会崩溃.要先导入MapKit框架(导入加引用)
- 部分显示地图(去哪等)必须关闭手势.(三个手势,拖拽,捏合,旋转)
- 显示用户所在位置(需要申请授权)
- 申请定位授权
- 设置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注释协议,自定义类类,遵守协议.
- 写三个协议内的属性.
MKAnnotationView地图注释View,就是大头针.
创建MKAnnotationView的子类
目标:希望继承这个类的MKAnnotation属性内的三个属性,并且还能新增功能属性.
1. 写一个同名属性
将@property (nonatomic, strong, nullable) id <MKAnnotation> 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介绍配置,不要遗漏就可以了.
目标:导入百度地图进行使用.
- 注册
- 简介和配置秘钥
- 重点看注意事项:
- 注意地图视图的生命周期
- 配置info.plist文件
下载SDK,以前是一个库.a文件,现在是多个.framework.方便了,只要导入相关的framework.(查阅百度官方解释)
注意:先不导,然后根据错误来导入.
- 添加相关framework
- 导入相关boundle(其实就是文件),内有资源
- 导入百度地图引用的系统框架.
- 解决object-C+=的问题.
- 修改某个文件的后缀为.mm (why?系统编译是根据文件类型来支持语言.mm就可以也支持ocject-C++了)
- 设置buildSetting.搜索compile source as,设置为object-C
- 解决boundle display name问题.表示项目名称.
- 加载BMKmapView,得到地图视图.注意额外注意生命周期问题.
注意真实项目中,所有的第三方SDK需要用单独的.h文件管理.永发哦了导入,不用pch文件.
- 代码:
- 初始化BMKMapManager,启动百度地图
- 使用百度地图.
https:在iOS9之后,苹果需要采用的安全传输协议https,需要配置的.
.framework是什么:库,框架.Xcode6以后推出的framework
- 百度地图的生命周期和代理设置的问题
Overlay遮盖.
ParkMark商圈标记点
目标:百度地图的定位功能
- 开始定位
- 百度地图的定位和地图功能是分开的.所以需要重新导入新的BMKLocation.framework.
- 核心类:BMKLocationService定位服务
- 类比原生:创建对象,设置代理返回数据.
- 开始定位(方法介绍,需要配置info.plist)
- 用户的位置数据模型
- 代理方法中BMKUserLocation参数:用户当前位置的大头针数据模型
- 错误处理:查找相关错误code,在BMKTypes.h文件中,查找
- 相关属性:desiredAccuary精确度.看官方解释
- 地图显示用户位置(搜mapView库location)
- 显示用户所在位置.
- 将用户数据传给地图,更新位置数据
结果:能显示位置,但是不会跳转到用户位置
- 设置地图显示区域
- 手动设置用户所在区域.
- setRegion方法,根据参数写位置.
- 导入工具模块.BMKUtils
- 获取用户的位置(便利操作:LocationService有更新位置的属性,定位后才是正确的)
- 追踪用户位置.
- 开启用户追踪模式
- 周期兴趣点查询(POI - ponit of interset)
POI:ATM,KTV,电影院等等- 导入searchAPI,有关的查找功能
- BMKPoiSearch类.
- 设置代理,需要在viewWillAppear配置和代理置空问题,否则影响释放.
- poiSearchNearBy方法参数option配置(很多需要配置,注意看一下,关键字等).
- 代理方法回调结果:查一下
- poiResult获取poiInfo类
- 大头针添加(mapView)
- 1.添加一个大头针数据,使用系统提供的表示一个点的大头针(找一下),不用自定义
2.根据你遍历模型数据,指定大头针.
- 1.添加一个大头针数据,使用系统提供的表示一个点的大头针(找一下),不用自定义
- 自定义大头针视图
- mapView的代理方法,返回某个模型对应的视图
- 判断类型BMKPointAnnotation返回对应的视图(类比原生)
- 创建BWKPinAnnotationView注意复用问题.
- 配置模型
- 需要改默认我的位置图片,但是不知道类型,代码改不了.
可以进入百度素材,改百度素材里面的图片名,并且注意同名.
新的东西:实现点击大头针触发弹出自定义窗口
- 百度的paopaoView.相似原生的自定义BMKAnnotationView.
- 有一个在这里上车的绿标大头针,他一直显示在屏幕的正中央.怎么做的?
- 把绿标不加载mapView上,而是加在view上.
- 获取绿标所在位置的经纬度描述.地图mapView提供了很多frame和坐标进行转化的方法.
// 转换坐标点 convertPoint方法返回一个坐标点.
- 利用反地理编码,获取详细信息.在search框架内.
- 周边标志性地表查找
- 通过反地理编码可以获取到周边的标志性地标.
- 反地理编码的poiList属性,就可以获取到周边信息了.