MapKit框架使用

MapKit框架使用

一.地图的基本使用

1.简介

  • MapKit:用于地图展示,例如大头针/路线/覆盖层展示等(着重界面展示)
  • 使用步骤:
    • 导入主头文件 MapKit/MapKit.h
    • MapKit有一个比较重要的UI控件:MKMapView,专门用于地图显示

2.显示类型/地图控制/显示控制

  • 设置地图类型
    • 地图的样式可以手动设置,在iOS9之前有3种,iOS9之后增加了2种
      • MKMapTypeStandard:普通地图
      • MKMapTypeSatellite:卫星云图
      • MKMapTypeHybrid:混合模式(普通地图覆盖于卫星云图之上)
      • MKMapTypeSatelliteFlyover:3D立体卫星(iOS9)
      • MKMapTypeHybridFlyover:3D立体混合(iOS9)
  • 设置方式:
    • self.mapView.mapType = MKMapTypeStandard;
  • 设置地图控制项
    • 地图的旋转/缩放/移动等操作行为都可以开启或关闭
    • 设置方式
      • 是否缩放:self.customMapView.zoomEnabled = YES;
      • 是否滚动:self.customMapVie.scrollEnabled = YES;
      • 是否旋转:self.customMapVie.rotateEnabled = YES;
      • 是否显示3DView:self.customMapVie.pitchEnable = NO;
  • 设置地图显示项
    • 地图上的指南针/比例尺/建筑物/POI点都可以控制是否显示
    • 设置方式
      • 是否显示指南针:self.customMapVie.showsCompass = YES;
      • 是否显示比例尺:self.customMapVie.showsScale = YES;
      • 是否显示交通:self.customMapVie.showsTraffic = YES;
      • 是否显示建筑物:self.customMapVie.showsBuildings = YES;
  • 常见问题总结
    • 地图加载不显示:
      • 检查网络是否通畅
    • 地图放大都是格子,禁止浏览:
      • 正常,为了安全原因,不能看的太详细
    • 地图运行起来app占用内存太大:
      • 正常,地图加载了很多资源
  • 测试环境
    • 加载地图数据需要联网
    • Xcode版本根据测试选择不同版本(iOS9只能使用Xcode7调试)
    • iOS版本根据测试选择不同版本(例如地图类型,在iOS9之后才有新增)

3.显示用户位置

  • 显示用户位置
    1. 可以设置显示用户当前所在位置,以一个蓝点的形式呈现在地图上
    2. 注意:如果要显示用户位置,在iOS8之后,需要主动请求用户授权
    3. 设置方案1:
      • 代码:self.customMapView.showUserLocation = YES;
      • 效果:会在地图上显示一个蓝点,标识用户所在的位置,但是地图不会缩放,而且当用户位置移动时,地图不会跟随用户位置移动而移动
    4. 设置方案2:
      • 代码:self.customMapView.userTrackingMode = MKUserTrackingModeFollowWithHeading;
      • 效果:会在地图上显示一个蓝点,标识用户所在的位置,而且地图缩放到合适比例,显示用户位置,当用户位置移动时,地图会跟随用户位置移动而移动,但是有时候失效
  • 用户位置不显示可能的原因
    • 检查代码,是否有设置显示用户的位置,是否有进行请求位置授权
    • 查看模拟器是否有位置信息
    • 重置模拟器

二.模拟器追踪显示用户位置

1.调整地图显示中心

  1. 设置地图代理
  2. 实现代理方法
    • mapView:didUpdateUserLocation:
  3. MKUserLocation大头针数据模型详解
    • MKUserLocation:被称作"大头针(数据)模型"
    • 本质就是一个数据模型,只不过此模型遵循了大头针要遵循的协议(MKAnnotation)
    • 重要属性:
      • location(CLLocation对象):用户当前所在位置信息
      • title(NSString对象):大头针标注要显示的标题
      • subtitle(NSString对象):大头针标注要显示的子标题
  4. 调整地图中心
    • 确定地图中心经纬度坐标
      • CLLocationCoordinate2D center = CLLocationCoordinate2DMake(xxx, xxx);
    • 设置地图中心为给定的经纬度坐标
      • [mapView setCenterCoordinate:center animated:YES];

2.调整地图显示区域

  1. 获取合适的区域
    • 实现当地图区域发生改变时调用的代理方法,并调整地图区域到合适比例,并在对应的方法中,获取对应的跨度信息
    • mapView:regionDidChangeAnimated:
  2. 创建一个区域(包含区域中心和区域跨度)
    • CLLocationCoordinate2D center = CLLocationCoordinate2DMake(xxx, xxx);
    • MKCoordinateSpan span = MKCoordinateSpanMake(0.1, 0.1)
    • MKCoordinateRegion region = MKCoordinateRegionMake(center, span);
  3. 设置地图显示区域
    • [self.mapView setRegion:region animated:YES];
  4. MKCoordianteSpan跨度解释
  • latitudeDelta:经度跨度,因为南北纬各90度,所以此值的范围是(0-180),此值表示整个地图视图的宽度,显示多大跨度
  • longtitudeDelta:纬度跨度,因为东西经各180度,所以此值的范围是(0-360),此值表示整个地图视图的高度,显示多大跨度
  • 注意:地图视图显示,不会更改地图的比例,会以地图视图高度或宽度较小的那个为基准,按比例调整

3.常见问题总结

  • 地图上蓝点不显示
    • 确定代码是否有误,是否显示用户位置
    • 确定模拟器是否设置位置
    • 可确定位置是否在当前地图显示区域
  • 地图跨度设置后,最终显示的跨度和设置数值不一致
    • 因为地球不是正方形的,随着用户的位置而移动,会自动修正地图跨度,保持地图不变形
  • 测试环境
    • 加载地图数据需要联网
    • Xcode版本不限/iOS系统版本不限

三.大头针基本使用

1.添加/删除

  • 理论支持
    • 按照MVC设计模式的原则(在地图上操作大头针,实际上是控制大头针数据模型)
    • 添加大头针就是添加大头针数据模型
    • 删除大头针就是删除大头针数据模型
  • 在地图上添加大头针视图
    • 自定义大头针数据模型
      • 创建继承自NSObject的数据模型CustomAnnotation
      • 遵循大头针数据模型必须遵守MKAnnotation协议
      • 注意将协议@property中的readonly去掉
    • 创建大头针数据模型,并初始化参数
      • CustomAnnotation *annotation = [[CustomAnnotation allco] init];
      • annotation.coordinate = coordinate;
      • annotation.title = @"喳喳";
      • annotation.subtitle = @"木喳喳的夏天";
    • 调用地图的添加大头针数据模型的方法
      • [self.customMapView addAnnotation:annotation];
  • 移除大头针视图(移除所有大头针)
    • NSArray *annotations = self.customMapView.annotations;
    • [self.customMapView removeAnnotations:annotations];

2.场景模拟

  • 场景描述
    • 手指/鼠标点击在地图哪个位置,就在对应的位置添加一个大头针,并在标注弹框中显示对应的城市和街道
  • 实现步骤
    1. 获取触摸点在地图上对应的坐标
    2. 将坐标转换为经纬度
    3. 根据经纬度创建大头针数据模型,并添加在地图上
    4. 利用反地理编码,,获取该点对应额城市和街道名称,然后修改大头针数据模型
    5. 注意:设置弹框数据时,对应的大头针数据模型应有对应的占位数据(这样对应的UI才会生成,后面才能重新修改数据)
  • 常见问题
    • 反地理编码无法获取对应的数据
      • 检查是否联网
      • 检查代码是否有误
      • 又是存在某些位置没有反地理编码结果,换个点尝试,如果都没有,排除此原因
    • 大头针协议遵循以及属性设置
      • @property其实就是生成get和set方法
      • 所以,遵循这个协议等同于实现了该属性的set/get方法

四.自定义大头针

1.模拟系统实现方案

  • 理论支持(依照MVC的原则)
    • 每当添加一个大头针数据模型时,地图就会调用对应的代理方法,查找对应的大头针视图,显示在地图上
    • 如果该方法没有实现,或者返回nil,那么就会使用系统默认的大头针视图
  • 模拟系统默认的实现方案
    • 实现当添加大头针数据模型时,地图回调的代理方法
      • mapView:viewForAnnotation:
    • 大头针对应的视图是MKPinAnnotationView,它继承自MKAnnotationView
    • 地图上的大头针视图,和tableView的cell一样,都使用"循环利用"的机制

2.自定义大头针和弹框

  • 实现当添加大头针数据模型时,地图回调的代理方法(mapView:viewForAnnotation)
  • 如果想要自定义大头针,必须使用MKAnnotationView或者自定义的子类
  • 但是不能直接使用系统默认的大头针,会无效

3.代理方法补充

  • 选中一个大头针时调用:mapView:didSelectAnnotationView:
  • 取消选中大头针时调用:mapView:didDeselectAnnotationView:

五.导航简介

  • 概念:简单来说,就是根据用户指定的位置,进行路线规划,然后根据用户在行走过程中,实时给出指引提示
  • 导航的三种实现方案:
    • 可以将需要导航的位置发送给系统的地图APP进行导航
    • 发送网络请求到公司服务器获取导航数据,然后自己手动绘制导航
    • 利用第三方SDK实现导航(百度)

六.使用系统APP进行导航

1.利用"反推发",记住关键代码即可

  • 根据MKMapItem数组和启动参数字典,来调用系统地图进行导航
  • 代码:[MKMapItem openMapsWithIterms:@[item1,item2] launchOptions:launchDic];
  • 注意:CLPlacemark地表对象没法直接手动创建,只能通过(反)地理编码获取

2.课题研究

  1. 3D视图
    • 类似于地图街景,增强用户体验
  2. 地图截图
    • 截图附加选项
      • MKMapSnapshotOptions *options = [[MKMapSnapshotOptions alloc] init];
    • 设置截图区域(在地图上的区域,作用在地图)
      • options.region = self.mapView.region;
    • 设置截图后的图片大小(作用在输出图像)
      • options.size = self.mapView.frame.size;
    • 设置截图后的图片比例(默认是屏幕比例,作用在输出图像)
      • options.scale = [[UIScreen mainScreen] scale];
    • 创建截图对象并开始截图
      • MKMapSnapshotter *snapshotter = [[MKMapSnapShotter alloc] initWithOptions:options];
      • [snapshotter startWithCompletionHandler:block];
  3. POI检索
let request = MKLocalSearchRequest()
request.naturalLanguageQuery = "小吃"
request.region = mapView.region let searcher: MKLocalSearch = MKLocalSearch(request: request)
searcher.startWithCompletionHandler { (response: MKLocalSearchResponse?, error: NSError?) in guard let items = response?.mapItems else { return }
for item in items {
print(item.name, item.phoneNumber, item.url)
} }

七.发送网络请求给苹果服务器进行导航

1.发送网络请求给苹果服务器获取导航路线

  • 实现须知
    • 获取导航路线,需要向苹果服务器发送网络请求
    • 记住关键对象MKDirections
  • 代码实现
    • 根据两个地标,向苹果服务器发送对应的行走路线信息
      • 创建请求
      • 设置开始地标
      • 设置结束地标
      • 根据请求,获取实际路线信息
        • MKDirections *directions = [[MKDirections alloc] initWithRequest:request];
        • [directions calculateDirectionWithCompletionHandler:block];
  • 测试环境
    • 请求路线数据需要联网
    • Xcode版本不限/iOS系统版本不限

2.解析导航数据

  • 导航路线对象详解
    • MKDirectionsResponse对象解析
      • source:开始位置
      • destination:结束位置
      • routes:路线信息(MKRoute对象)
    • MKRoute对象解析
      • name:路的名称
      • advisoryNotices:注意警告信息
      • distance:路线长度(实际物理距离,单位是m)
      • polyline:路线对应在地图上的几何线路数据模型(由很多点组成,可绘制在地图上)
      • steps:多个行走步骤组成的数组(例如"前方路口左转","保持之行"等,MKRouteStep对象)
    • MKRouteStep对象解析
    • instruction:步骤说明(例如"前方路口左转","保持之行"等)
    • transportType:交通方式(驾车,步行等)
    • polyline:路线对应在地图上的几何线路数据模型(由很多点组成,可绘制在地图上)
    • 注意:MKRoute是一整条长路,MKRouteStep是这条长路中的每一截
  • 常见问题总结
    • 类太多,记不住,只需要知道有这么一个功能即可,如果用到时,直接回头找代码即可.

3.绘制导航路线

  • 理论支持
    • 路线也是一个覆盖层
    • 在地图上操作覆盖层,其实操作的是覆盖层的数据模型
      • 添加覆盖层:在地图上添加覆盖层数据模型
      • 删除覆盖层:在地图上移除覆盖层数据模型
  • 添加导航路线到地图
    1. 获取几何路线的数据模型(id)overlay
    2. 在地图上添加覆盖层(几何路线也是一个覆盖层),直接添加覆盖层数据模型
      • [self.mapView addOverlay:overlay];
    3. 设置地图代理,代理遵循MKMapViewDelegate协议
    4. 实现地图添加覆盖层数据模型时,回调的代理方法,通过此方法,返回对应的渲染图层
      • mapView:renderForOverlay:
  • 添加圆形覆盖层到地图
    • 创建圆形区域覆盖层的数据模型
    • 添加覆盖层数据模型
    • 实现代理方法
  • 测试环境
    • 地图加载需要联网
    • Xcode版本不限/iOS系统版本不限
  • 常见问题总结
    • 类太多,记不住怎么办?
      • 只需要记住一个思想,按照MVC的原则,我们操作覆盖层,就是操作覆盖层数据模型
      • 然后地图会调用其对应的代理方法,获取对应的覆盖层渲染层

八.使用第三方SDK进行导航

1.集成百度地图sdk

  • 集成原因
    • 有些功能,系统自带的高德地图无法实现,例如POI检索等
    • 一般实现导航功能,集成百度地图的比较多
  • 集成步骤
    1. 注册用户并登陆百度地图开放平台
    2. 根据需求,选择不同的sdk
    3. 下载对应的sdk
    4. 按照集成文档一步步实现
  • 文档说明
    • 创建应用,并获取秘钥(注意APP BundleID的配置要和项目工程一致)
    • 参照集成文档,配置对应的开发环境
      • 工程中至少有一个.mm后缀的源文件(一般修改代理文件的后缀为AppDelegate.mm)
      • Other Linker Flags中添加"-Objc"(Swift与OC进行混编)
      • iOS9.0ATS适配(将Allow Arbitrary Loads设置为YES)
      • iOS8.0定位适配(设置NSLocationAlwaysUsageDescription为定位说明文字)
      • 在info.plist中添加Bundle display name为"$(PRODUCT_NAME)"
      • 添加系统的依赖库
        • CoreLocation.framework
        • QuartzCore.framework
        • OpenGLES.framework
        • SystemConfiguration.framework
        • CoreGraphics.framework
        • Security.framework
        • libsqlite3.0.tbd(xcode7以前为 libsqlite3.0.dylib)、CoreTelephony.framework
        • libstdc++.6.0.9.tbd(xcode7以前为libstdc++.6.0.9.dylib
      • 引入mapapi.bundle资源文件(注意: 需要单独导入,放在.framework中,拖入不到工程)
    • 根据功能需求,实现不同的功能代码

2.使用百度地图进行POI检索/添加大头针/集成百度导航SDK/定位及导航

3.代码封装重构

  • 不要把所有的功能全部都写在控制器当中,最好封装成一个单独的工具类
  • 如果集成过程中出现问题,先查看官方文档
上一篇:LinuxC语言读取文件,分割字符串,存入链表,放入另一个文件


下一篇:【深入浅出Linux网络编程】 “实践 -- TCP & UDP”