iOS核心笔记—MapKit框架-基础

1、MapKit框架简介:

?了解:MapKit框架使用须知:①、MapKit框架中所有的数据类型的前缀都是MK;②、需要导入#import <MapKit/MapKit.h>头文件;③、MapKit框架中有一个非常重要的UI控件:MKMapView,专门用于地图显示,例如:大头针、路线、覆盖层展示等(着重界面展示)。


1-1、地图设置:
1-1-1、设置地图显示类型:

地图类型

地图枚举 地图类型
MKMapTypeStandard 普通地图
MKMapTypeSatellite 卫星云图
MKMapTypeHybrid 混合模式(普通地图覆盖于卫星云图之上 )
MKMapTypeSatelliteFlyover 3D立体卫星(iOS9.0
MKMapTypeHybridFlyover 3D立体混合(iOS9.0

?备注:通过MKMapViewmapType属性可以设置地图类型,iOS9.0新出的属性在我国不能使用。


1-1-2、设置地图控制项:

地图控制项

地图控制项 地图类型
mapView.zoomEnabled 地图是否可以缩放
mapView.scrollEnabled 地图是否可以滚动
mapView.rotateEnabled 地图是否可以旋转
mapView.pitchEnabled 地图是否显示3D效果

?备注:通过设置这些属性,可以控制地图的旋转、缩放、移动等操作行为。


1-1-3、设置地图显示项:

地图显示项

地图显示项 地图类型
mapView.showsCompass 是否显示指南针
mapView.showsScale 是否显示比例尺
mapView.showsTraffic 是否显示交通状况
mapView.showsBuildings 是否显示建筑物
mapView.showsPointsOfInterest 是否显示兴趣点
mapView.showsUserLocation 是否显示用户的位置

?了解:地图上的指南针、比例尺、建筑物、POI点都可以控制是否显示。


1-2、使用注意:

?注意-1:从iOS7.0开始可以不用手动导入框架,使用MapKit框架中的类创建对象时便会隐式的导入MapKit框架;但是,如果是直接从storyboard中拖入MKMapView控件,则需要手动导入MapKit框架,否则,运行时将报无法正常创建mapView的错误。?



?注意-2:加载地图数据需要联网。


2、大头针基本使用:

?重要:大头针在mapView上显示的任何数据都是由其对应的大头针数据模型所决定的。


2-1、显示用户位置:
1.#import "ViewController.h"2.#import <MapKit/MapKit.h>3.[email protected] ViewController () <MKMapViewDelegate>5./** 地图控件 */[email protected] (weak, nonatomic) IBOutlet MKMapView *mapView;7./** 位置管理者对象 */[email protected] (strong, nonatomic) CLLocationManager *mgr;9.[email protected]11.[email protected] ViewController13.14.- (void)viewDidLoad {15.    [super viewDidLoad];16.17.    // 1. 创建位置管理者对象18.    self.mgr = [CLLocationManager new];19.20.    // 2. 请求定位授权21.    if ([self.mgr respondsToSelector:@selector(requestWhenInUseAuthorization)]) {22.        [self.mgr requestWhenInUseAuthorization];23.    }24.25.    // 3. 设置用户跟踪模式, 以便在mapView中显示用户的位置26.//    self.mapView.userTrackingMode = MKUserTrackingModeFollow;27.    self.mapView.userTrackingMode = MKUserTrackingModeFollowWithHeading;28.29.    // 4. 设置mapView的代理, 监听mapView上用户的移动30.    self.mapView.delegate = self;31.}32.33.#pragma mark - MKMapViewDelegate34.35./**36. mapView中用户位置更新完毕调用37. */38.- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation{39.    NSLog(@"%@", userLocation.location);40.}41.[email protected]

?备注:显示自定义大头针标题:在mapView代理方法中,结合反地理编码;将大头针模型中的location属性反地理编码,以便获取详细的地标对象(CLPlacemark);再从地标对象中获取具体的位置信息,将具体的位置信息设置到大头针模型属性中,以便大头针展示。这里有几个注意点:①、从大头针数据模型中取出位置对象(CLLocation),再将位置对象进行反地理编码获取包含详细地址信息的地标对象(CLPlacemark);再将地标对象中的详细地址信息设置到大头针数据模型中,将来大头针控件便能将大头针数据模型中的数据显示在mapView上面。



显示用户位置模式

模式 作用
MKUserTrackingModeNone = 0 默认模式, 不显示用户位置
MKUserTrackingModeFollow = 1 显示用户位置, 无方向箭头; 常用于只需要显示用户位置
MKUserTrackingModeFollowWithHeading = 2 显示用户位置, 并显示方向箭头; 常用于导航


MKUserLocation(模型)

属性 作用
updating 判断用户位置是否已更新
location 位置对象
heading 设备朝向
title 触摸大头针显示的标题
subtitle 触摸大头针显示的子标题

?备注:MKUserLocation对应的是显示用户位置的“蓝色光圈”大头针数据模型,其所有属性都为readonly


2-2、模拟追踪显示用户位置:

?重要:设置以用户所在位置为mapView中心点,因为,用户当前所在位置相对于mapView来说是固定的(即:不能移动用户的位置到mapView现有显示区域的中心点,移动用户位置至mapView现有显示区域中心点去显示用户位置便没有任何意义);所以,在不移动用户位置的前提下在mapView的显示区域的中心点位置显示用户当前所在位置便需要依靠改变mapView的显示区域来完成。切记:是改变mapView的显示区域,以达到在mapView的中心点位置显示用户位置;千万不要误认为是修改用户的位置。


1.#import "ViewController.h"2.#import <MapKit/MapKit.h>3.[email protected] ViewController () <MKMapViewDelegate>5./** 地图控件 */[email protected] (weak, nonatomic) IBOutlet MKMapView *mapView;7./** 位置管理者对象 */[email protected] (strong, nonatomic) CLLocationManager *mgr;9.[email protected]11.[email protected] ViewController13.14.- (void)viewDidLoad {15.    [super viewDidLoad];16.17.    // 1. 创建位置管理者对象18.    self.mgr = [CLLocationManager new];19.20.    // 2. 请求定位授权21.    if ([self.mgr respondsToSelector:@selector(requestWhenInUseAuthorization)]) {22.        [self.mgr requestWhenInUseAuthorization];23.    }24.25.    // 3. 设置用户跟踪模式, 以便在mapView中显示用户的位置26.    self.mapView.userTrackingMode = MKUserTrackingModeFollowWithHeading;27.28.    // 4. 设置mapView的代理, 监听mapView上用户的移动29.    self.mapView.delegate = self;30.}31.32./**33. 设置用户当前所在位置为mapView显示区域中心点坐标34. mapView显示区域 : 当前展示在手机屏幕中的区域即为显示区域35. */36.- (IBAction)backMapCenter:(UIButton *)sender {37.    // MARK: - 方式一 : 设置mapView的centerCoordinate属性,38.    // 只能改变mapView中心点坐标, 无法改变跨度39.//    self.mapView.centerCoordinate = self.mapView.userLocation.location.coordinate;40.    // 带动画的方式41.    [self.mapView setCenterCoordinate:self.mapView.userLocation.location.coordinate animated:YES];42.43.    // MARK: - 方式二 : 设置mapView的region属性44.    // 能同时改变mapView的中心点位置、显示区域的跨度45.    // 1. 创建显示区域中心点坐标46.    CLLocationCoordinate2D center = self.mapView.userLocation.location.coordinate;47.48.    // 2. 设置显示区域的跨度49.    MKCoordinateSpan span = MKCoordinateSpanMake(0.01, 0.01);50.51.    // 3. 动画设置用户位置为mapView中心点位置52.    [self.mapView setRegion:MKCoordinateRegionMake(center, span) animated:YES];53.}54.55./**56. mapView显示区域会调用该方法, 在该方法中能够获取mapView系统的跨度57. */58.- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated{59.    NSLog(@"latitudeDelta : %lf, longitudeDelta : %lf", mapView.region.span.latitudeDelta, mapView.region.span.longitudeDelta);60.}[email protected]

?说明:设置用户当前所在位置为中心点的两种方式:①、直接修改mapView的centerCoordinate属性,直接将用户所在位置设置为该属性的值,但是,这种方式一旦修改mapView的显示跨度、用户所在位置之后,虽然能将用户所在位置设置为mapView中心点位置,但是,mapView的显示区域跨度无法还原(即:如果没有手动还原mapView的显示区域跨度,那么,跨度将一直保持在改变之后的值),即:该方式不能合理改变显示跨度;②、设置mapView的region属性,因为region属性包含两个成员center、span,通过设置该属性能够将用户当前所在位置设置为mapView的显示区域中心点位置,而且还能同时设置mapView显示区域的跨度。注意:如果需要动画将用户所在位置设置为mapView的中心点坐标应当使用属性对应的带有动画的set方法,而不是直接设置用户的属性。



?补充:当mapView的显示区域发生变化后,会调用mapView:regionDidChangeAnimated:代理方法,在该代理方法中可以通过mapView.region.span.longitudeDelta、mapView.region.span.latitudeDelta分别获取系统的经纬度跨度;这样,在我们设置用户当前所在位置为mapView中心点坐标的时候便可以使用系统的跨度,在mapView的中心点坐标修改之后,mapView显示区域的跨度为系统跨度;避免每次修改mapView的中心点坐标的时候导致mapView显示区域的跨度不一致。


2-3、缩放地图:

?了解:放大、缩小地图,实质是修改mapView的region.span的值;是对应方向上的跨度发生变化。


1./**2. 放大地图, 实质是减小跨度值3. */4.- (IBAction)zoomInClick:(UIButton *)sender {5.    // 1. 修改跨度6.    CLLocationDegrees latitudeDelta = self.mapView.region.span.latitudeDelta * 0.5;7.    CLLocationDegrees longitudeDelta = self.mapView.region.span.longitudeDelta * 0.5;8.9.    // 2. 重置mapView的region10.    self.mapView.region = MKCoordinateRegionMake(self.mapView.region.center, MKCoordinateSpanMake(latitudeDelta, longitudeDelta));11.}12.13./**14. 缩小地图, 实质是增大跨度值15. */16.- (IBAction)zoomOutClick:(UIButton *)sender {17.    // 1. 修改跨度18.    CLLocationDegrees latitudeDelta = self.mapView.region.span.latitudeDelta * 2;19.    CLLocationDegrees longitudeDelta = self.mapView.region.span.longitudeDelta * 2;20.21.    // 2. 重置mapView的region22.    self.mapView.region = MKCoordinateRegionMake(self.mapView.region.center, MKCoordinateSpanMake(latitudeDelta, longitudeDelta));23.}

?步骤:①、跨度倍数处理;②、重设region属性。


3、自定义大头针:

3-1、自定义大头针数据模型:

?重要:所有自定义大头针数据模型必须遵守MKAnnotation协议。



详细步骤

步骤 详细说明
第一步 导入MapKit框架
第二步 自定义模型类继承自NSObject,遵守MKAnnotation协议
第三步 拷贝协议中的所有属性, 并删除readonly
第四步 创建自定义大头针数据模型对象
第五步 自定义大头针数据模型对象添加到mapView中

?重要:为什么要删除readonly?因为,要设置大头针相关属性,如果不删除readonly,那么,大头针数据模型中所有的属性都为只读的,将来使用该模型添加到mapView中时,无法显示数据。



自定义大头针数据模型

1.#import <Foundation/Foundation.h>2.#import <MapKit/MapKit.h>3.[email protected] MyAnnotationModel : NSObject <MKAnnotation>5./** 大头针位置 */[email protected] (nonatomic) CLLocationCoordinate2D coordinate;7./** 大头针标题 */[email protected] (nonatomic, copy, nullable) NSString *title;9./** 大头针子标题 */[email protected] (nonatomic, copy, nullable) NSString *subtitle;11.[email protected]


使用自定义大头针数据模型

1.#import "ViewController.h"2.#import <MapKit/MapKit.h>3.#import "MyAnnotationModel.h"4.[email protected] ViewController ()6./** 地图视图 */[email protected] (weak, nonatomic) IBOutlet MKMapView *mapView;8.[email protected]10.[email protected] ViewController12.13.- (void)viewDidLoad {14.    [super viewDidLoad];15.16.    // 1. 创建大头针数据模型17.    MyAnnotationModel *model = [MyAnnotationModel new];18.19.    // 2. 设置大头针数据模型属性20.    model.coordinate = CLLocationCoordinate2DMake(40, 116);21.    model.title = @"帝都";22.    model.subtitle = @"充满魅力的城市";23.24.    // 3. 添加到mapView25.    [self.mapView addAnnotation:model];26.}27.28.- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{29.    // 1. 获取触摸点坐标30.    CGPoint point = [[touches anyObject] locationInView:self.mapView];31.32.    // 2. 将点转换为经纬度33.    CLLocationCoordinate2D coordinate = [self.mapView convertPoint:point toCoordinateFromView:self.mapView];34.35.    // 3. 创建自定义大头针数据模型36.    MyAnnotationModel *model = [MyAnnotationModel new];37.38.    // 4. 设置大头针数据模型相关属性39.    model.coordinate = coordinate;40.    model.title = @"圣安东尼奥";41.    model.subtitle = @"诸葛维奇_马刺队";42.43.    // 5. 添加到mapView44.    [self.mapView addAnnotation:model];45.}46.[email protected]

?说明:注意通过mapView的convertPoint:toCoordinateFromView:方法能够将触摸在屏幕上的点转换为mapView上面的经纬度。


3-2、自定义大头针视图:

?重要:与大头针视图相关的类:MKAnnotationView、MKPinAnnotationView;当往mapView中添加“大头针数据模型”时,便会来到mapView的mapView:viewForAnnotation:代理方法询问代理该“返回大头针视图”;当该代理方法没有实现、或者返回“nil”时,大头针视图默认交由系统自动处理,系统会根据实际需求决定是返回显示用户位置的“蓝色光圈”、或者返回其他样式的大头针视图。



详细步骤

步骤 详细说明
第一步 创建大头针视图静态重用标识
第二步 从缓存池中查找是否有可重用的大头针视图
第三步 判断大头针视图是否创建成功,如果创建不成功,则手动创建大头针视图(通常使用MKAnnotationView的子类MKPinAnnotationView创建大头针视图)
第四步 给大头针视图设置属性值(MKPinAnnotationView类才有相关属性)
第五步 返回大头针视图

?注意:在代理方法中,使用MKAnnotationView创建大头针视图并返回;将来mapView中显示大头针视图时,默认不显示,因为,大头针视图没有颜色。


1.#import "ViewController.h"2.#import <MapKit/MapKit.h>3.#import "MyAnnotationModel.h"4.[email protected] ViewController () <MKMapViewDelegate>6./** 地图视图 */[email protected] (weak, nonatomic) IBOutlet MKMapView *mapView;8./** 位置管理者对象 */[email protected] (strong, nonatomic) CLLocationManager *mgr;10.[email protected]12.[email protected] ViewController14.15.- (void)viewDidLoad {16.    [super viewDidLoad];17.18.    // MARK: - 定位授权19.    // 1. 创建位置管理者对象20.    self.mgr = [CLLocationManager new];21.22.    // 2. 请求授权, 使用如下形式进行授权操作, 等价于已经做好版本适配操作23.    // 因为, iOS8.0之前, 位置管理者对象没有requestWhenInUseAuthorization方法24.    if ([self.mgr respondsToSelector:@selector(requestWhenInUseAuthorization)]) {25.        [self.mgr requestWhenInUseAuthorization];26.    }27.28.    // MARK: - 添加大头针29.    // 1. 创建大头针数据模型30.    MyAnnotationModel *model = [MyAnnotationModel new];31.32.    // 2. 设置大头针数据模型属性33.    model.coordinate = CLLocationCoordinate2DMake(40, 116);34.    model.title = @"帝都";35.    model.subtitle = @"充满魅力的城市";36.37.    // 3. 添加到mapView38.    [self.mapView addAnnotation:model];39.40.    // MARK: - 设置mapView相关属性41.    self.mapView.userTrackingMode = MKUserTrackingModeFollow;  // 显示用户位置42.    self.mapView.delegate = self;  // 设置代理43.}44.45.- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{46.    // 1. 获取触摸点坐标47.    CGPoint point = [[touches anyObject] locationInView:self.mapView];48.49.    // 2. 将点转换为经纬度50.    CLLocationCoordinate2D coordinate = [self.mapView convertPoint:point toCoordinateFromView:self.mapView];51.52.    // 3. 创建自定义大头针数据模型53.    MyAnnotationModel *model = [MyAnnotationModel new];54.55.    // 4. 设置大头针数据模型相关属性56.    model.coordinate = coordinate;57.    model.title = @"圣安东尼奥";58.    model.subtitle = @"诸葛维奇_马刺队";59.60.    // 5. 添加到mapView61.    [self.mapView addAnnotation:model];62.}63.64./**65. 当mapView添加"大头针数据模型"时, 便会来到该方法返回"大头针视图"66. 没有实现该代理方法、或者返回为nil, 表示大头针视图类型由系统决定67.68. @param mapView 地图视图69. @param annotation 大头针数据模型70. @return 大头针视图71. */72.- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{73.    // 0. 显示系统类型大头针视图74.    if ([annotation isKindOfClass:[MKUserLocation class]]) {75.        // 返回nil, 表示大头针视图类型由系统决定76.        return nil;77.    }78.79.    // 1. 定义静态重用标识80.    static NSString *ID = @"annotation";81.82.    // 2. 从缓存池中查找可重用的大头针视图83.    // MKAnnotationView : 该类型大头针视图默认image属性为nil, 不显示84.    // MKPinAnnotationView : 为MKAnnotationView的子类, 默认为红色85.//    MKAnnotationView *annot = [self.mapView dequeueReusableAnnotationViewWithIdentifier:ID];86.    MKPinAnnotationView *pin = (MKPinAnnotationView *)[self.mapView dequeueReusableAnnotationViewWithIdentifier:ID];87.88.    // 3. 判断缓存池是否有可重用的大头针视图89.    if (pin == nil) {90.        pin = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:ID];91.92.        // MARK: - 设置大头针视图属性93.        // 1. 设置颜色94.        // pinTintColor : iOS9.0设置大头针视图颜色属性95.        // pinColor : iOS9.0之前设置大头针颜色属性96.        pin.pinTintColor =  [UIColor colorWithRed:((float)arc4random_uniform(256) / 255.0) green:((float)arc4random_uniform(256) / 255.0) blue:((float)arc4random_uniform(256) / 255.0) alpha:1.0];97.98.        // 2. 设置动画掉落99.//        pin.animatesDrop = YES;100.    }101.102.    // 4. 返回大头针视图103.    return pin;104.}[email protected]

?注意:自定义大头针视图时,为避免覆盖显示用户位置“蓝色光圈”;需要对大头针数据模型进行判断:mapView中显示用户位置的“蓝色光圈”也是一种大头针视图,其对应的数据模型类型为:MKUserLocation。所以,当我们实现代理方法返回自定义大头针视图时,一定要对“蓝色光圈”大头针视图进行判断;避免自定义大头针视图覆盖“蓝色光圈”(即:如果在代理方法中未加判断,直接返回自定义大头针视图;将来在mapView中添加“大头针数据模型”时,mapView中显示的所有的大头针视图全都为自定义类型的大头针视图;显示用户位置的“蓝色光圈”也被自定义大头针视图给覆盖)。


?补充-1:在mapView中,当我们需要显示用户位置时,等价于需要定位当前用户所在位置;所以,在iOS8.0之后需要进行定位授权操作;否则,无法显示用户位置。备注:授权操作两步曲:①、配置plist文件相应的键值对,key为NSLocationWhenInUseUsageDescription/NSLocationAlwaysUsageDescription;②、使用代码请求授权,位置管理者对象调用requestWhenInUseAuthorization/requestAlwaysAuthorization方法请求授权。二者缺一不可。

?补充-2:MKAnnotationView的image属性可以设置大头针视图的图片,当我们自定义大头针视图时,默认该属性的值为nil。

?补充-3:自定义大头针视图,使用MKAnnotationView,让大头针视图显示自定义图片,根据MVC思想,在大头针数据模型中新增image属性,在代理方法中,根据大头针数据模型的image属性创建图片并设置为自定义大头针视图的image。注意:一个大头针对应一个大头针数据模型。增加一个大头针视图,只需要增加一个大头针数据模型;删除一个大头针,只需要删除一个大头针数据模型。


4、模拟系统大头针掉落动画效果:

?重要:自定义大头针视图,并模拟系统大头针掉落动画效果。其原理时在大头针未显示之前将大头针视图移动至屏幕上方外面,然后,再以动画的形式将大头针从屏幕外面移动至屏幕中指定位置;所有操作都在mapView的mapView:didAddAnnotationViews:方法中完成。模拟系统大头针动画调用效果的本质:是在mapView的代理方法中,动态改变大头针视图的frame。


4-1、详细步骤:
步骤 详细说明
第一步 记录大头针在mapView中要显示的位置
第二步 将大头针视图的frame设置到屏幕外
第三步 在UIView动画中将大头针视图的frame还原至之前需要显示的位置。注意事项:所有操作必须是在大头针还未显示前的代理方法中执行,在给自定义大头针视图添加掉落动画效果时需要对显示用户位置的“蓝色光圈”大头针进行特殊处理;通过大头针视图对应的大头针数据模型的类型进行区分,避免“蓝色光圈”也带有掉落动画效果。记得要在返回大头针视图的代理方法中设置大头针的image属性

4-2、示例代码:
1.#import "ViewController.h"2.#import "MyAnnotationModel.h"3.#import "MyAnnotationView.h"4.5.#import <MapKit/MapKit.h>6.[email protected] ViewController () <MKMapViewDelegate>8./** 地图视图 */[email protected] (weak, nonatomic) IBOutlet MKMapView *mapView;10./** 位置管理者对象 */[email protected] (strong, nonatomic) CLLocationManager *mgr;12.[email protected]14.[email protected] ViewController16.17.- (void)viewDidLoad {18.    [super viewDidLoad];19.20.    // MARK: - 请求授权21.    // 1. 创建位置管理者对象22.    self.mgr = [CLLocationManager new];23.24.    // 2. 请求授权25.    if ([self.mgr respondsToSelector:@selector(requestWhenInUseAuthorization)]) {26.        [self.mgr requestWhenInUseAuthorization];27.    }28.29.    // MARK: - 设置mapView属性30.//    self.mapView.userTrackingMode = MKUserTrackingModeFollow;31.    self.mapView.delegate = self;32.}33.34.- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{35.    // MARK: - 大头针一36.    MyAnnotationModel *model1 = [MyAnnotationModel new];37.    model1.coordinate = CLLocationCoordinate2DMake(40, 116);38.    model1.title = @"帝都";39.    model1.subtitle = @"充满魔力的城市";40.    model1.icon = @"苍老师";41.    [self.mapView addAnnotation:model1];42.43.    // MARK: - 大头针二44.    MyAnnotationModel *model2 = [MyAnnotationModel new];45.    model2.coordinate = CLLocationCoordinate2DMake(23, 108);46.    model2.title = @"东莞";47.    model2.subtitle = @"充满美丽的城市";48.    model2.icon = @"自拍照";49.    [self.mapView addAnnotation:model2];50.}51.52.53.#pragma mark - <MKMapViewDelegate>54./**55. 当往mapView中添加数据模型时, 便会来到此代理方法中返回大头针视图56. 通常在该方法中自定义大头针视图, 该方法返回nil默认大头针视图类型由系统处理57.58. @param mapView 地图59. @param annotation 大头针模型60. @return 大头针视图61. */62.- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{63.    // 1. 如果是"蓝色光圈", 则由系统决定64.    if ([annotation isKindOfClass:[MKUserLocation class]]) {65.        return nil;66.    }67.68.    // 2. 创建大头针视图69.    MyAnnotationView *annotationView = [MyAnnotationView annotationViewWithMapView:mapView];70.71.    // 3. 返回大头针视图72.    return annotationView;73.}74.75./**76. 大头针视图还未显示时会调用该方法77.78. @param mapView 地图79. @param views 所有大头针视图80. */81.- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray<MKAnnotationView *> *)views{82.    // 如果没有大头针视图, 则直接返回83.    if (views.count == 0) {84.        return ;85.    }86.87.    // 遍历大头针视图数组, 添加掉落动画88.    for (MKAnnotationView *annotView in views) {89.        // 1. 如果是"蓝色光圈", 则不需要添加动画90.        if ([annotView.annotation isKindOfClass:[MKUserLocation class]]) {91.            continue;  // 记住: 此处是使用continue, 因为还需要进行下一次遍历操作92.        }93.94.        // 2. 记录大头针显示位置95.        CGRect endFrame = annotView.frame;96.97.        // 3. 改变大头针的frame98.        annotView.frame = CGRectMake(annotView.frame.origin.x, -80, annotView.bounds.size.width, annotView.bounds.size.height);99.100.        // 4. 动画还原大头针至原定显示位置101.        [UIView animateWithDuration:3.0 animations:^{102.            annotView.frame = endFrame;103.        }];104.    }105.}106.[email protected]

5、封装自定义大头针视图:

示例代码一:大头针视图内部实现

1.#import "MyAnnotationView.h"2.#import "MyAnnotationModel.h"3.[email protected] MyAnnotationView5.6.+ (instancetype)annotationViewWithMapView:(MKMapView *)mapView{7.    // 1. 定义静态重用标识8.    static NSString *ID = @"annotationView";9.10.    // 2. 从缓存池中查找11.    MyAnnotationView *annotationView = (MyAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:ID];12.13.    // 3. 判断缓存池中是否有可重用的大头针视图14.    if (annotationView == nil) {15.        annotationView = [[MyAnnotationView alloc] initWithAnnotation:nil reuseIdentifier:ID];16.    }17.18.    // 4. 返回大头针视图19.    return annotationView;20.}21.22./**23. 无论外界是否有使用到大头针的模型属性, 系统都会自动调用该方法24. 重写该方法之后, 一定要调用super方法; 否则, 程序直接崩溃25. */26.- (void)setAnnotation:(id<MKAnnotation>)annotation{27.    [super setAnnotation:annotation];28.29.    // 4.1. 设置大头针图片, 一旦自定义大头针视图, image默认为: nil30.    MyAnnotationModel *model = annotation;  // 强转31.    self.image = [UIImage imageNamed:model.icon];32.33.    // 4.2 显示标题/子标题, 自定义大头针视图默认为: NO, 将不显示标题/子标题/辅助视图34.    self.canShowCallout = YES;35.36.    // 4.3 左右辅助视图37.    self.leftCalloutAccessoryView = [UISwitch new];38.    self.rightCalloutAccessoryView = [UISwitch new];39.40.    // 4.4 iOS9.0 新增属性: 标题下面可以设置详细视图, 设置该属性之后将会覆盖子标题41.    self.detailCalloutAccessoryView = [UISwitch new];42.}43.[email protected]


示例代码二:外界使用

1.#import "ViewController.h"2.#import "MyAnnotationModel.h"3.#import "MyAnnotationView.h"4.5.#import <MapKit/MapKit.h>6.[email protected] ViewController () <MKMapViewDelegate>8./** 地图视图 */[email protected] (weak, nonatomic) IBOutlet MKMapView *mapView;10./** 位置管理者对象 */[email protected] (strong, nonatomic) CLLocationManager *mgr;12.[email protected]14.[email protected] ViewController16.17.- (void)viewDidLoad {18.    [super viewDidLoad];19.20.    // MARK: - 请求授权21.    // 1. 创建位置管理者对象22.    self.mgr = [CLLocationManager new];23.24.    // 2. 请求授权25.    if ([self.mgr respondsToSelector:@selector(requestWhenInUseAuthorization)]) {26.        [self.mgr requestWhenInUseAuthorization];27.    }28.29.    // MARK: - 设置mapView属性30.//    self.mapView.userTrackingMode = MKUserTrackingModeFollow;31.    self.mapView.delegate = self;32.}33.34.- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{35.    // MARK: - 大头针一36.    MyAnnotationModel *model1 = [MyAnnotationModel new];37.    model1.coordinate = CLLocationCoordinate2DMake(40, 116);38.    model1.title = @"帝都";39.    model1.subtitle = @"充满魔力的城市";40.    model1.icon = @"苍老师";41.    [self.mapView addAnnotation:model1];42.43.    // MARK: - 大头针二44.    MyAnnotationModel *model2 = [MyAnnotationModel new];45.    model2.coordinate = CLLocationCoordinate2DMake(23, 108);46.    model2.title = @"东莞";47.    model2.subtitle = @"充满美丽的城市";48.    model2.icon = @"自拍照";49.    [self.mapView addAnnotation:model2];50.}51.52./**53. 当往mapView中添加数据模型时, 便会来到此代理方法中返回大头针视图54. 通常在该方法中自定义大头针视图, 该方法返回nil默认大头针视图类型由系统处理55.56. @param mapView 地图57. @param annotation 大头针模型58. @return 大头针视图59. */60.- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{61.    // 1. 如果是"蓝色光圈", 则由系统决定62.    if ([annotation isKindOfClass:[MKUserLocation class]]) {63.        return nil;64.    }65.66.    // 2. 创建大头针视图67.    MyAnnotationView *annotationView = [MyAnnotationView annotationViewWithMapView:mapView];68.69.    // 3. 返回大头针视图70.    return annotationView;71.}72.[email protected]

?说明-1:自定义大头针视图,点击大头针时,除了显示标题、子标题外;可以通过设置MKAnnotationView的leftCalloutAccessoryView、rightCalloutAccessoryView属性,可以在标题的左侧显示辅助视图。注意:当我们自定义大头针视图时,MKAnnotationView的canShowCallout属性默认为:NO;该属性值为NO时,左辅助视图不显示,所以,如果我们想实现自定义大头针视图显示左、右辅助视图时,必须设置canShowCallout属性的值为YES,否则,标题、子标题、左右辅助视图都将不会显示。

?说明-2:MKAnnotationView在iOS9.0新增detailCalloutAccessoryView属性,该属性用以展示详细信息,一旦设置该属性之后,子标题将不再显示。

?说明-3:封装创建自定义大头针视图,在外界提供一个创建自定义大头针视图的类方法即可。

?说明-4:封装大头针view与封装cell的过程几乎一模一样,唯一一个地方不一样的是封装大头针view可以不用给大头针view传递数据模型;直接在外界使用大头针视图,在自定义大头针view的内部系统会自动调用模型的set方法;给大头针view设置数据,如果重写模型的set方法,一定要调用super;否则,程序将直接崩溃;在重写的模型set方法中我们可以将一些大头针view的通用设置封装进去(例如:给大头针设置图片),快速创建大头针view的方法只需要传入mapView即可。


时间: 2024-08-06 15:59:00

iOS核心笔记—MapKit框架-基础的相关文章

iOS核心笔记—CoreLocation框架-基础

1.CoreLocation框架简介: ?了解:在iOS开发中,要想使用地图和定位功能,必须基于2个框架进行开发.CoreLocation框架:主要用于地理定位:MapKit框架:主要用于地图展示. 1-1.CoreLocation框架功能: 功能 作用 地理定位 定位用户所在位置,获取对应的经纬度.海拔等位置信息 区域监听 事先在APP内部通过代码指定一个区域,当用户进入.或离开该区域的时候,可以通过对应的代理方法监听到用户的位置 地理编码 将详细的位置信息转换为对应的经纬度,即:位置信息 -

iOS核心笔记—MapKit框架-导航

1.导航简介: ?了解:导航,简单来说,就是根据用户指定的位置,进行路线规划:然后根据用户在行走过程中,实时的给出指引提示. 1-1.iOS导航实现方案: 方案 详细说明 方案一 将需要导航的位置传递给系统的地图APP进行导航 方案二 发送网络请求到Apple服务器/公司服务器获取导航数据,然后,手动绘制导航路线 方案三 利用第三方SDK实现导航功能(百度地图) ?说明:通常如果需要手动绘制导航路线,都是向Apple服务器发送请求.获取导航信息:此处,只对方案一.方案二做详细介绍,方案三将单独说

iOS核心笔记——UICollectionView-布局对象

iOS核心笔记--UICollectionView-布局对象 1.UICollectionView布局对象: 1-1.UICollectionViewLayout: ?了解:1.UICollectionViewLayout没有itemSize属性,而collectionView的cell的大小不能为0或者小于0:所以,通常collectionView使用其子类UICollectionViewFlowLayout布局cell. ?了解:2.UICollectionViewLayout中声明了布局可

iOS核心笔记——UICollectionView-辅助视图

iOS核心笔记--UICollectionView-辅助视图 1.UICollectionView辅助视图: ?了解:UICollectionView中的头部视图.尾部视图都是使用注册机制 + 重用机制,提高程序的执行效率,其头尾部视图类型均为:UICollectionReusableView.注册辅助视图时使用字符串区分注册的视图为头部还是尾部视图,其区分字符串为:UICollectionElementKindSectionHeader(头部视图).UICollectionElementKin

iOS学习笔记—— MapKit

在iOS应用程序中,我们可以使用Map Kit API开发地图应用,其核心是MKMapView类.本次主要实现的功能是显示地图,添加标注,跟踪用户位置变化. (本日志的所有内容基于已成功获取坐标位置,获取方法见上篇日志) 1.显示地图 首先需要引用<MapKit/MapKit.h>,它的委托协议是 MKMapViewDelegate. 初始化MapView mapView = [[MKMapView alloc] initWithFrame:CGRectMake(5, 120, self.vi

iOS核心笔记——多线程-GCD

1.GCD简介: ?了解:GCD全称为"Grand Central Dispatch",纯C语言,GCD提供了非常多功能强大的函数:GCD中所有的函数都包含于Libdispatch库中. 1-1.使用GCD的优势: ?了解:1.GCD是苹果公司为多核的并行运算提出的解决方案: ?了解:2.GCD会自动利用更多的CPU内核(例如:双核.四核): ?了解:3.GCD会自动管理线程的生命周期(创建线程.调度任务.销毁线程). 1-2.GCD两大核心概念: 名称 作用: 任务 执行什么操作 队

iOS核心笔记——网络编程-网络安全

1.数据安全: 1.01 攻城利器:Charles(公司中一般都使用该工具来抓包,并做网络测试)2.注意:Charles在使用中的乱码问题,可以显示包内容,然后打开info.plist文件,找到java目录下面的VMOptions,在后面添加一项:-Dfile.encoding=UTF-83.02 数据安全的原则4. 1)在网络上"不允许"传输用户隐私数据的"明文"5. 2.)在本地"不允许"保存用户隐私数据的"明文"6.03

iOS核心笔记——RunLoop-基础

1.RunLoop介绍: ?了解:RunLoop从字面意思看就是运行循环.跑圈,通常情况下,一个线程一次只能执行一个任务:任务执行完毕后线程就会进入消亡状态随之退出.有时候我们希望线程执行完任务之后还能随时处理事件且不退出,所以,iOS提供了RunLoop. 1-1.什么是RunLoop? ?重要:RunLoop实际上就是一个对象,RunLoop对象管理其需要处理的事件和消息:RunLoop能够让线程在没有处理消息时进入休眠状态以避免占用资源.在监听到事件源发送的消息时立刻唤醒线程.RunLoo

iOS核心笔记——网络编程-HTTPS协议

1.HTTPS的基本使用: 1.HTTPS简单说明: ?了解:HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版. ?重要:即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL. 它是一个URI scheme(抽象标识符体系),句法类同http:体系.用于安全的HTTP数据传输. ?重要:https:URL:表明它使用了HTTPS,