首先,我们需要知道的是一个大头针必须确定的是他的经纬度坐标
(一)大头针的简单实使用,无需自定义(只能是大头针扎进地图)
1.因为系统自带的类MKAnnotation的属性是readonly,如果我们要设置这些属性值的话我们只能自己自定义一个属性然后继承MKAnnotation
@interface TLLAnnotation : NSObject<MKAnnotation>
@property (nonatomic,assign) CLLocationCoordinate2D coordinate;//坐标
@property (nonatomic, copy) NSString *title;//大头针标题
@property (nonatomic, copy) NSString *subtitle;//大头针子标题
@end
2.在viewController里面增加mapView属性,遵循 MKMapViewDelegate 协议,使得大头针扎进这个mapView里面
#import "ViewController.h"
#import "TLLAnnotation.h"
@interface ViewController ()<MKMapViewDelegate>
@property (nonatomic,strong) MKMapView *mapView;
@end
@implementation ViewController
- (MKMapView *)mapView {
if (!_mapView) {
_mapView = [[MKMapView alloc]initWithFrame:self.view.bounds];
[self.view addSubview:_mapView];
}
return _mapView;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.mapView.delegate = self;
TLLAnnotation *anno1 = [[TLLAnnotation alloc]init];
anno1.coordinate = CLLocationCoordinate2DMake(37, 116);
anno1.title = @"不知道是哪";
anno1.subtitle = @"hhhahahhhhahahha";
[self.mapView addAnnotation:anno1];
TLLAnnotation *anno2 = [[TLLAnnotation alloc]init];
anno2.coordinate = CLLocationCoordinate2DMake(29, 110);
anno2.title = @"还是不知道是哪";
anno2.subtitle = @"gububuvvuuuuuuuuuu";
[self.mapView addAnnotation:anno2];
}
@end
这样,基本的定位就实现了,效果如下
但是,如果我们需要自定义大头针的颜色,更改大头针下落的效果,或者是有上百上千个大头针,我们还需要考虑到循环引用大头针,而此时,MKMapViewDelegate的代理方法
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation 完全可以帮助我们达到效果
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
NSString *reuseIdentifier = @"reuseIdentifier";
// 1.先从缓存池中取出可以循环利用的大头针控件
MKPinAnnotationView *annotationView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:reuseIdentifier];
// 2.缓存池中没有可以循环利用的大头针控件
if (!annotationView) {
// 传入循环利用标识来创建大头针控件
annotationView = [[MKPinAnnotationView alloc]initWithAnnotation:nil reuseIdentifier:reuseIdentifier];
// 设置头的颜色
annotationView.pinTintColor = [UIColor purpleColor];
// 显示标题和子标题
annotationView.canShowCallout = YES;
// 从天而降
annotationView.animatesDrop = YES;
// 显示标题和子标题
annotationView.calloutOffset = CGPointMake(0, -10);
annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeContactAdd];
annotationView.leftCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeInfoDark];
// 往大头针里面添加一个按钮
//[annotationView addSubview:[UIButton buttonWithType:UIButtonTypeContactAdd]];
}
// 3.传递模型(更新大头针数据,覆盖掉之前的旧数据)
annotationView.annotation = annotation;
return annotationView;
}
恩,此时虽然可以自定义了,但是我们还可以将要自定义的代码进行一个封装,顺便将大头针换成我们喜欢的图形吧,比如说各种团购的定位面对各种成百上千的大头针,进行一个分类那想必是再好不过的了(比如说是美食,旅游等)
1.新增MKAnnotationView类,并增加方法
TLAnnotationView.h文件
<span style="font-family: Menlo;">#import <MapKit/MapKit.h></span>
@interface TLAnnotationView : MKAnnotationView
+ (instancetype)annotationViewWithMapView:(MKMapView *)mapView;
@end
<pre name="code" class="objc" style="color: rgb(76, 191, 87); font-size: 14px;">TLAnnotationView.m文件(封装大头针)
<pre name="code" class="objc">#import "TLAnnotationView.h"
#import "TLLAnnotation.h"
@interface TLAnnotationView()
@property (nonatomic,weak) UIImageView *iconView;
@end
@implementation TLAnnotationView
//将大头针放进相应的mapView
+ (instancetype)annotationViewWithMapView:(MKMapView *)mapView {
NSString *reuseIdentifier = @"reuseIdentifier";
TLAnnotationView *annoView = (TLAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:reuseIdentifier];
if (!annoView) {
// 传入循环利用标识来创建大头针控件
annoView = [[TLAnnotationView alloc]initWithAnnotation:nil reuseIdentifier:reuseIdentifier];
}
return annoView;
}
//进行一些初始化的设置
- (id)initWithAnnotation:(id<MKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier {
if ([super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier]) {
//显示标题和子标题
self.canShowCallout = YES;
//左边显示一个图片
UIImageView *image = [[UIImageView alloc]init];
image.bounds = CGRectMake(0, 0, 30, 30);
self.leftCalloutAccessoryView = image;
self.iconView = image;
}
return self;
}
- (void)setAnnotation:(TLLAnnotation *)annotation {
[super setAnnotation:annotation];
self.image = [UIImage imageNamed:annotation.iconView];
self.iconView.image = self.image;
}
@end
2.在TLLAnotation类中增加图片属性
<pre name="code" class="objc">#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
@interface TLLAnnotation : NSObject<MKAnnotation>
@property (nonatomic,assign) CLLocationCoordinate2D coordinate;//坐标
@property (nonatomic, copy) NSString *title;//大头针标题
@property (nonatomic, copy) NSString *subtitle;//大头针子标题
//新增图片属性
@property (nonatomic,copy) NSString *iconView;
@end
3.代理方法即可简化如下
<pre name="code" class="objc">- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(TLLAnnotation *)annotation{
// 返回nil就会按照系统的默认做法
if (![annotation isKindOfClass:[TLLAnnotation class]]) return nil;
// 1.获得大头针控件
TLAnnotationView *annoView = [TLAnnotationView annotationViewWithMapView:mapView];
// 2.传递模型
annoView.annotation = annotation;
return annoView;
}
运行结果如下图所示,这样一来,自定义图片基本完成
尽管已经到了如此的地步,但是我们此时还并未满意,你有没有发现有时候点击annotationView的时候我们需要的并不是他自带的view,他或许是一个tableView,或许是一个clooectionView,又或者其他,这时候在下面这个方法中写点击annotation弹出的各种View即可
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
UIButton *redView = [[UIButton alloc] init];
[redView addTarget:self action:@selector(redClick) forControlEvents:UIControlEventTouchUpInside];
redView.backgroundColor = [UIColor redColor];
redView.width = 20;
redView.height = 20;
redView.y = - redView.height;
redView.x = (self.width - redView.width) * 0.5;
[self addSubview:redView];
self.redView = redView;
UIButton *greenView = [[UIButton alloc] init];
[greenView addTarget:self action:@selector(greenClick) forControlEvents:UIControlEventTouchUpInside];
greenView.backgroundColor = [UIColor greenColor];
greenView.width = 20;
greenView.height = 20;
greenView.y = 20;
greenView.x = 20;
[self addSubview:greenView];
self.greenView = greenView;
}
运行效果如下:
我们需要自定义 的图形即可
在处理点击事件的时候,因为红色View已经到了annotationView的外面,所以点击它并没有进入到redClick,为了拦截住redClick,我们需要增加一个方法
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
if (CGRectContainsPoint(self.redView.frame, point)) {
return self.redView;
}
return [super hitTest:point withEvent:event];
}
这样,redClick和greenClick就都会响应并且不会混乱了,至于这个方法的作用,将在下面的博客里面在做介绍。
MKAnnotation创建一个类继承