文章目录
简介
CoreLocation框架能够获取经纬度信息,但是实际的App中,使用更加普遍的是地理位置与地图的结合应用,例如我们常见的打车软件,可以在地图上实时显示用户当前的位置,而地理位置与地图的综合应用需要使用到MapKit框架。
属性
在MapKit框架中,最重要的一个类就是MKMapView类。MKMapView类可以为用户提供一个展示地图的界面,程序员可以在地图上进行进一步的功能定制。在MKMapView类中,有如下一些比较常用的属性和方法。
设置地图的展示类型。在MKMapView中提供了三种地图展示的方式,分别为MKMapTypeStandard(标准图)、MKMapTypeSatellite(卫星图)、MKMapTypeHybrid(混合图),我们最常用的是MKMapTypeStandard(标准图)。
@property (nonatomic) MKMapType mapType;
当前地图的中心坐标。通常情况下,我们可以获取用户的当前位置,并且赋值给centerCoordinate属性。
@property (nonatomic) CLLocationCoordinate2D centerCoordinate;
设置显示区域的范围。
@property (nonatomic) MKCoordinateRegion region;
设置MKMapView的代理对象,MKMapView的代理对象需要遵守MKMapViewDelegate协议。
@property (nonatomic, weak, nullable) id <MKMapViewDelegate> delegate;
设置地图是否可缩放,默认可缩放。
@property (nonatomic, getter=isZoomEnabled) BOOL zoomEnabled;
用户追踪模式。
@property (nonatomic) MKUserTrackingMode userTrackingMode;
获取的用户的位置坐标。MKUserLocation类中提供了一个CLLocation类型的属性location,可以用户获取用户的位置信息。
@property (nonatomic, readonly) MKUserLocation *userLocation;
是否显示交通情况。
@property (nonatomic) BOOL showsTraffic;
是否显示比例尺。
@property (nonatomic) BOOL showsScale;
是否显示指南针。
@property (nonatomic) BOOL showsCompass;
用圆点显示用户位置
self.mapView.userTrackingMode = MKUserTrackingModeFollow;
MKMapViewDelegate代理协议
MKMapView中定义了MKMapViewDelegate代理协议,在该代理协议中提供了用于监测MKMapView加载过程的方法。
地图即将开始加载时调用。
- (void) mapViewWillStartLoadingMap:(MKMapView *)mapView;
地图加载完毕后调用。
-(void)mapViewDidFinishLoadingMap:(MKMapView *)mapView;
地图加载失败调用。
- (void)mapViewDidFailLoadingMap:(MKMapView *)mapView withError:(NSError *)error;
用户位置更新时调用,该方法调用非常频繁,可以不断监测用户的当前位置,通过其提供的userLocation参数,我们可以获取到用户的最新位置信息。
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation;
地图的显示的区域即将发生改变的时候调用。
- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated;
地图的显示区域已经发生改变的时候调用。
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated;
自定义“大头针”样式。
- (nullable MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation;
MKMapView基本使用
准备工作:当我们需要使用MapKit框架时,需要预先导入MapKit框架。
#import "ViewController.h"
#import <MapKit/MapKit.h>
@interface ViewController ()<MKMapViewDelegate>
@property (nonatomic,strong)MKMapView *mapView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.mapView];
}
- (MKMapView *)mapView{
if (_mapView==nil) {
_mapView=[[MKMapView alloc]init];
//设置mapView的属性
_mapView.frame=[UIScreen mainScreen].bounds;
_mapView.mapType=MKMapTypeStandard;
_mapView.delegate=self;
_mapView.zoomEnabled=YES;
_mapView.showsScale=YES;
_mapView.showsTraffic=YES;
_mapView.showsCompass=YES;
//指定地图的中心点经纬度,我们也可以通过CoreLocation框架获取用户当前的坐标
_mapView.centerCoordinate=CLLocationCoordinate2DMake(32.04, 118.76);
//地图显示的范围
MKCoordinateSpan span={0.05,0.05};
_mapView.region=MKCoordinateRegionMake( _mapView.centerCoordinate, span);
}
return _mapView;
}
@end
简要地图标注
当我们在地图上搜索某个地址时,搜索结果会以一个“大头针”的样式插在地图上,这些“大头针”就是地图上的标注。“大头针”不仅可以显示某个地址在地图中的位置,同时还可以显示该地址的一些附加信息,例如,在外卖应用中,可以标注商家的名称以及联系方式等。
MKAnnotaiton协议
在地图上展示的标注,都必须遵守MKAnnotaiton协议。在该协议中,可以获取地图标注的属性。
获取标注的经纬度信息。
@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
获取标注的标题信息
@property (nonatomic, readonly, copy, nullable) NSString *title;
@property (nonatomic, readonly, copy, nullable) NSString *subtitle;
MKPointAnnotation类
MKPointAnnotation类是在MapKit框架中系统定义的标注类,该类继承自MKShape类,由于MKShape类遵守MKAnnotaiton协议,因此,作为MKShape类的子类,MKPointAnnotation类也遵守MKAnnotaiton协议。MKPointAnnotation类的标注样式是由系统提供的,即一个红头的大头针样式的标注,也是我们最常见的样式。创建MKPointAnnotation对象后,我们需要给其设置经纬度信息(coordinate)。
@interface MKPointAnnotation : MKShape
@property (nonatomic, assign) CLLocationCoordinate2D coordinate;
@end
而MKShape类中,提供了可以设置地图标注标题的属性。
@interface MKShape : NSObject <MKAnnotation>
@property (nonatomic, copy, nullable) NSString *title;
@property (nonatomic, copy, nullable) NSString *subtitle;
@end
结合前面的介绍,有如下两种方式可以创建地图标注对象:
创建MKPointAnnotation类的对象,其父类遵守了MKAnnotaiton协议;
创建一个自定义类,设置该类遵守MKAnnotaiton协议。
标注的添加与删除操作
在MKMapView类中,不仅可以展示地图信息,同样提供了用于在地图上设置标注的方法,常用的包括添加标注以及移除标注等。添加的标注对象都需要遵守MKAnnotaiton协议。
添加一个标注。
- (void)addAnnotation:(id <MKAnnotation>)annotation;
添加多个标注。
- (void)addAnnotations:(NSArray<id<MKAnnotation>> *)annotations;
移除一个标注。
- (void)removeAnnotation:(id <MKAnnotation>)annotation;
移除多个标注。
- (void)removeAnnotations:(NSArray<id<MKAnnotation>> *)annotations;
简单举例
-(void)addPoint{
MKPointAnnotation *annotation=[[MKPointAnnotation alloc]init];
[annotation setCoordinate:self.mapView.centerCoordinate];
[annotation setTitle:@"侵华日军南京大屠杀遇难同胞纪念馆"];
[annotation setSubtitle:@"南京市建邺区水西门大街418号"];
[self.mapView addAnnotation:annotation];
}
复杂地图标注(MKAnnotationView)
借助MKPointAnnotation类,我们可以快速的创建地图标注,但MKPointAnnotation类的标注样式是由系统定义的,程序员不能够对其样式进行修改。在实际的开发中,为了体现App的特性,我们有时会需要对地图标注的样式进行自定义。当我们需要创建复杂地图标注时,就需要使用MKAnnotationView。
MKAnnotationView简介
MKAnnotationView类是MapKit框架中提供的类,用于创建复杂的地图标注。在MKAnnotationView类中,提供了用于定制标注左侧、右侧以及“大头针”样式的属性。例如在滴滴打车中的图标样式,我们就可以为其添加左侧的视图以及更新其“大头针”样式图标。
MKAnnotationView类继承自UIView,在该类提供的API中,提供了用于定制地图标注样式的属性,有如下几个需要重点掌握。
实例化方法。需要传入一个遵守MKAnnotation协议的参数,用于提供标注所在的位置,因此,当我们创建MKAnnotationView对象之前,需要提前创建一个遵守MKAnnotation协议的对象作为参数传入。
- (instancetype)initWithAnnotation:(nullable id <MKAnnotation>)annotation reuseIdentifier:(nullable NSString *)reuseIdentifier;
设置标注显示的图片。
@property (nonatomic, strong) UIImage *image;
设置标注右边的控件样式。
@property (strong, nonatomic) UIView *rightCalloutAccessoryView;
设置标注左边的控件样式。
@property (strong, nonatomic) UIView *leftCalloutAccessoryView;
设置标注下面的显示控件(需要iOS9.0+)。
@property (nonatomic, strong) UIView *detailCalloutAccessoryView;
点击标注后,是否显示标注的详细信息。
@property (nonatomic) BOOL canShowCallout;
MKAnnotationView的设置方法
假如希望地图标注使用自定义的样式,需要在MKMapViewDelegate代理协议中的mapView:viewForAnnotation:方法中完成。在该方法中,可以传入添加到MKMapView上的每一个annotation对象,因此我们可以为不同的annotation设置不同的标注样式。
- (nullable MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation;
MKPinAnnotationView类
MKPinAnnotationView类是MKAnnotationView类的子类,在MKPinAnnotationView类中提供了一些快速设置默认标注样式的方法,主要体现在可以对“大头针”的颜色进行设置。
@property (NS_NONATOMIC_IOSONLY, strong, null_resettable) UIColor *pinTintColor;
另外,在MKPinAnnotationView类中,还提供了一个地图标注从天而降的动画效果。
@property (nonatomic) BOOL animatesDrop;
复杂地图标注示例
本节的示例代码,在MKMapView上实现了添加自定义样式的地图标注,该地图标注的图标使用自定义图片,点击图标后,可以在附加视图的左右两侧各添加一个按钮。
- 准备工作
在进行地图标注样式定制之前,需要提前完成如下代码的编写:
初始化一个MKMapView类的对象,并设置属性;
初始化一个MKPointAnnotation类的对象,设置其属性,并添加到MKMapView对象上;
设置MKMapView对象的代理对象,通常为控制器对象,然后设置控制器对象遵守MKMapViewDelegate协议
添加MKMapView到控制器视图上。
使用自定义样式的地图标注,需要在MKMapViewDelegate代理协议中的mapView:viewForAnnotation:方法中完成。
//
// ViewController.m
// MapKit_base
//
// Created by on 2019/8/5.
// Copyright © 2019 Shae. All rights reserved.
//
#import "ViewController.h"
#import <MapKit/MapKit.h>
@interface ViewController ()<MKMapViewDelegate>
@property (nonatomic,strong)MKMapView *mapView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.mapView];
//要有复杂的标注,必须要有基本标注
[self addPoint];
}
- (MKMapView *)mapView{
if (_mapView==nil) {
_mapView=[[MKMapView alloc]init];
//设置mapView的属性
_mapView.frame=[UIScreen mainScreen].bounds;
_mapView.mapType=MKMapTypeStandard;
_mapView.delegate=self;
_mapView.zoomEnabled=YES;
_mapView.showsScale=YES;
_mapView.showsTraffic=YES;
_mapView.showsCompass=YES;
//指定地图的中心点经纬度,我们也可以通过CoreLocation框架获取用户当前的坐标
_mapView.centerCoordinate=CLLocationCoordinate2DMake(32.04, 118.76);
//地图显示的范围
MKCoordinateSpan span={0.05,0.05};
_mapView.region=MKCoordinateRegionMake( _mapView.centerCoordinate, span);
}
return _mapView;
}
-(void)addPoint{
MKPointAnnotation *annotation=[[MKPointAnnotation alloc]init];
[annotation setCoordinate:self.mapView.centerCoordinate];
[annotation setTitle:@"侵华日军南京大屠杀遇难同胞纪念馆"];
[annotation setSubtitle:@"南京市建邺区水西门大街418号"];
[self.mapView addAnnotation:annotation];
}
//代理方法中实现复杂标注
- (nullable MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation{
if([annotation isKindOfClass:[MKPointAnnotation class]]){
MKAnnotationView *customAnnotationView=(MKAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:@"CustomPinAnnotationView"];
if (customAnnotationView==nil) {
customAnnotationView=[[MKAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:@"CustomPinAnnotationView"];
}
//设置标注的图片
customAnnotationView.image=[UIImage imageNamed:@"1"];
//设置点击标注可以显示更多信息
customAnnotationView.canShowCallout=YES;
//右键按钮定制
UIButton *rightButton=[[UIButton alloc]initWithFrame:CGRectMake(0, 0, 50, 50)];
rightButton.backgroundColor=[UIColor redColor];
[rightButton setTitle:@"前往" forState:normal];
customAnnotationView.rightCalloutAccessoryView=rightButton;
//左键按钮定制
UIButton *leftButton=[[UIButton alloc]initWithFrame:CGRectMake(0, 0, 50, 50)];
leftButton.backgroundColor=[UIColor blueColor];
[leftButton setTitle:@"详情" forState:normal];
customAnnotationView.leftCalloutAccessoryView=leftButton;
return customAnnotationView;
}
return nil;
}
@end