1. 自定义大头针视图
前文中,我们看到添加的大头针在地图上显示的形式都是一样的,采用系统默认的大头针样式。在一些应用中系统默认的大头针样式可能无法满足实际的需求,此时就需要修改大头针视图默认样式。事实上,MKMapView的代理方法- (MKAnnotationView )mapView:(MKMapView )mapView viewForAnnotation:(id )annotation;可以返回一个大头针视图,只要实现这个方法并在这个方法中定义一个大头针视图MKAnnotationView对象并设置相关属性就可以改变默认大头针的样式。当然如果代理方法返回nil则会使用默认大头针视图,需要根据情况设置,比如添加的大头针数据为用户当前位置(MKUserAnnotation)。
通过上面的代理方法自定义大头针视图需要注意代理方法的调用时机:每当有大头针显示到系统可视界面中时就会调用此方法返回一个大头针视图放到界面中,同时当前系统位置标注(也就是地图中蓝色的位置点)也是一个大头针,也会调用此方法,因此处理大头针视图时需要区别对待(通过大头针数据模型)。另外类似于UITableView的代理方法,此方法调用频繁,开发过程中需要重复利用MapKit的缓存池将大头针视图缓存起来重复利用。自定义大头针默认情况下不允许交互,如果交互需要设置属性显示大头针视图的标题以区分大头针视图。下面是MKAnnotationView的常用属性:
属性 | 说明 |
---|---|
annotation | 大头针模型信息,包括标题、子标题、地理位置。 |
image | 大头针图片 |
canShowCallout | 点击大头针是否显示标题、子标题内容等,注意如果在- (MKAnnotationView )mapView:(MKMapView )mapView viewForAnnotation:(id )annotation;方法中重新定义大头针默认情况是无法交互的需要设置为true。 |
calloutOffset | 点击大头针时弹出详情信息视图的偏移量 |
selected | 是否被选中状态 |
leftCalloutAccessoryView | 弹出详情左侧视图 |
rightCalloutAccessoryView | 弹出详情右侧视图 |
从上面的属性中,我们不难看出,当我们自定义大头针视图时,除了可以添加大头针的图片之外,我们还可以设置更多的大头针视图属性,比如弹出视图、偏移量等信息。
示例代码:
自定义大头针数据模型:
Annotation.h 大头针数据模型
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
@interface Annotation : NSObject<MKAnnotation>
@property (nonatomic, assign) CLLocationCoordinate2D coordinate;
@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *subtitle;
// 自定义一个图片属性在创建大头针视图时使用
@property (nonatomic, copy)NSString *imageName;
@end
添加大头针数据,并返回大头针视图
#import "ViewController.h"
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
#import "Annotation.h"
@interface ViewController ()<CLLocationManagerDelegate,MKMapViewDelegate>
@property (nonatomic, strong)CLLocationManager *locationManager;
@property (nonatomic, strong)MKMapView *mapView;
@end
@implementation ViewController
- (CLLocationManager *)locationManager {
if (!_locationManager) {
_locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = self;
}
return _locationManager;
}
- (MKMapView *)mapView {
if (!_mapView) {
_mapView = [[MKMapView alloc] initWithFrame:self.view.bounds];
//设置地图样式
_mapView.mapType = MKMapTypeStandard;
//设置用于追踪模式
_mapView.userTrackingMode = MKUserTrackingModeFollow;
_mapView.delegate = self;
}
return _mapView;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.mapView];
//1.判断手机定位服务是否打开
if (![CLLocationManager locationServicesEnabled]) {
NSLog(@"手机定位服务没有打开");
return;
}
//2.iOS8.0以上的用户需要授权
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined) {
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) {
//调用此方法之前必须在plist文件中添加NSLocationWhenInUseUsageDescription --string-- 后面跟的文字就是提示信息
[self.locationManager requestWhenInUseAuthorization];
}
}
}
// 添加大头针数据模型
- (void)addAnnotation {
// 酒店大头针数据
Annotation *anno1 = [[Annotation alloc] init];
anno1.coordinate = CLLocationCoordinate2DMake(39.9, 116);
anno1.title = @"xxx酒店";
anno1.subtitle = @"周末8折,会员5折";
anno1.imageName = @"category_3";
[self.mapView addAnnotation:anno1];
// 影院大头针
Annotation *anno2 = [[Annotation alloc] init];
anno2.coordinate = CLLocationCoordinate2DMake(40, 117);
anno2.title = @"xxx影院";
anno2.subtitle = @"《夏洛 特 烦恼》 正在热映,周末免费";
anno2.imageName = @"category_5";
[self.mapView addAnnotation:anno2];
}
#pragma mapViewDelegate
/**
* 用户位置发生改变的时候调用这个方法
*
* @param mapView 地图
* @param userLocation 地图上蓝色的那颗大头针数据(注意不是那个蓝色的视图)
*/
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
userLocation.title = @"北京市";
userLocation.subtitle = @"中国首都";
NSLog(@"%f , %f",userLocation.location.coordinate.latitude,userLocation.location.coordinate.longitude);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//设置地图显示的区域
//获取中心点位置
CLLocationCoordinate2D center = userLocation.location.coordinate;
//显示跨度
MKCoordinateSpan span = MKCoordinateSpanMake(4.193344,