• 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.代码封装重构

    • 不要把所有的功能全部都写在控制器当中,最好封装成一个单独的工具类
    • 如果集成过程中出现问题,先查看官方文档
  • 相关阅读:
    iOS9 News 应用
    swift中,Optional、?与!之间的关系
    [翻译] CotEditor
    [book] iOS 8 Swift Programming Cookbook
    便利的操作plist文件
    消除 Xcode7 中 directory not found for option 'xxxx' 警告
    点击单个cell高度变化的动画效果
    [翻译] LiquidFloatingActionButton
    一脸懵逼学习Zookeeper(动物园管理员)---》高度可靠的分布式协调服务
    一脸懵逼学习基于CentOs的Hadoop集群安装与配置(三台机器跑集群)
  • 原文地址:https://www.cnblogs.com/coderwjq/p/6214746.html
Copyright © 2020-2023  润新知