自定义大头针Annotation

(1)自定义大头针Annotation的样式,也就是定义view,主要的方法是如下,传递一个大头针annotation模型,然后返回一个 MKAnnotationView,这个MKAnnotationView有一个image属性,设置这个属性,就能设置它的样式了。

-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id)annotation{

}

关键提示,这个MKAnnotationView和tableViewCell类似,可以循环利用,先从mapView中取,取不到再创建。

主要代码:

#import "ViewController.h"

#import

#import

#import "WPAnnotation.h"

@interface ViewController ()

@property (weak, nonatomic) IBOutlet MKMapView *mapView;

@property(nonatomic,strong) CLLocationManager *locMgr;

@end

@implementation ViewController

-(CLLocationManager *)locMgr{

if (_locMgr==nil) {

_locMgr=[[CLLocationManager alloc]init];

}

return _locMgr;

}

- (void)viewDidLoad {

[super viewDidLoad];

if ([[UIDevice currentDevice].systemVersion doubleValue]>=8.0) {

[self.locMgr requestWhenInUseAuthorization];

}

//设置代理

self.mapView.delegate=self;

//添加两个大头针

WPAnnotation *anno0=[[WPAnnotation alloc]init];

anno0.coordinate=CLLocationCoordinate2DMake(40, 116);

anno0.title=@"全聚德";

anno0.subtitle=@"全北京最好的烤鸭店";

anno0.icon=@"category_1";

[self.mapView addAnnotation:anno0];

WPAnnotation *anno1=[[WPAnnotation alloc]init];

anno1.coordinate=CLLocationCoordinate2DMake(39, 115);

anno1.title=@"万达影院";

anno1.subtitle=@"全中国最顶尖的观影圣地";

anno1.icon=@"category_5";

[self.mapView addAnnotation:anno1];

}

-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id)annotation{

static NSString *ID=@"annoView";

MKAnnotationView *annoView=[mapView dequeueReusableAnnotationViewWithIdentifier:ID];

if (annoView==nil) {

annoView=[[MKAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:ID];

//点击大头针出现信息(自定义view的大头针默认点击不弹出)

annoView.canShowCallout=YES;

}

//再传递一次annotation模型(赋值)

annoView.annotation=annotation;

WPAnnotation *anno=annotation;

annoView.image=[UIImage imageNamed:anno.icon];

return annoView;

}

@end

大头针模型,多了一个icon属性,因为我们要自定义大头针,所以需要图形属性:

#import

#import

@interface WPAnnotation : NSObject

@property (nonatomic, assign) CLLocationCoordinate2D coordinate;

@property (nonatomic, copy) NSString *title;

@property (nonatomic, copy) NSString *subtitle;

//自定义大头针图片

@property(nonatomic,copy) NSString *icon;

@end

(2)如果我们加入追踪用户现有位置时

//追踪用户位置self.mapView.userTrackingMode=MKUserTrackingModeFollow;

发现会有如下报错: [MKUserLocation icon]: unrecognized selector sent to instance 0x7f89baecab50

主要原因是,追踪用户位置的MKUserLocation也是一个大头针(蓝色发光的那个圈圈),它也要经过viewForAnnotation 这个代理方法返回自定义的大头针,但是它是没有icon属性的,所以报错。我们应该在viewForAnnotation中添加一个判断:

//如果是系统自带的大头针,则返回默认的,否则下面要设置icon时会报错,因为系统的大头针没有icon属性

if (![annotation isKindOfClass:[WPAnnotation class]]) return nil;

(3)还有一个MKPinAnnotationView是MKAnnotationView的子类,属性多2个,一个是设置颜色,就是可以设置大头针的颜色,还有一个是设置大头针从天而降。

- (void)viewDidLoad {

[super viewDidLoad];

......

[self.mapView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapMapView:)]];

}

-(void)tapMapView:(UITapGestureRecognizer *)tap{

//获取点

CGPoint point=[tap locationInView:tap.view];

//点转坐标

CLLocationCoordinate2D coordi=[self.mapView convertPoint:point toCoordinateFromView:self.mapView];

WPAnnotation *anno=[[WPAnnotation alloc]init];

anno.coordinate=coordi;

anno.title=@"全聚德";

anno.subtitle=@"来一只鸭子,老板!";

[self.mapView addAnnotation:anno];

}

-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id)annotation{

static NSString *ID=@"map";

MKPinAnnotationView *annoView=(MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:ID];

if (annoView==nil) {

annoView=[[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:ID];

//设置描述信息能点击出现

annoView.canShowCallout=YES;

//设置颜色

annoView.pinColor=MKPinAnnotationColorGreen;

//设置第一次出现从天而降

annoView.animatesDrop=YES;

}

return annoView;

}

(4)自定义一个MKAnnotationView,并利用代理方法,监听大头针的点击,点击后,再弹出一个“大头针”(只不过这个大头针是自定义MkAnnotationView的)。

我们一般返回一个大头针视图,用下面这个类似于tableViewCell的方法。

-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id)annotation{

if ([annotation isKindOfClass:[WPDescriptionAnnotation class]]) {

WPAnnotationView *annoView=[WPAnnotationView annotationWithMapView:mapView];

annoView.annotation=annotation;

return annoView;

}else if ([annotation isKindOfClass:[WPAnnotation class]]){

WPTuanGouAnnotationView *annoView=[WPTuanGouAnnotationView annotationWithMapView:mapView];

annoView.annotation=annotation;

return annoView;

}

return nil;

}

点击某一个大头针视图,也类似于点击tableView的某一行(这里有一些判断语句十分实用):

//点击大头针,弹出一个自定义的大头针充当描述信息

-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view{

if (![view isKindOfClass:[WPTuanGouAnnotationView class]]) return;

//删除所有再添加,保证只有1个,也防止重复

for (id annotation in mapView.annotations) {

if ([annotation isKindOfClass:[WPDescriptionAnnotation class]]) {

[mapView removeAnnotation:annotation];

}

}

WPAnnotation *anno=view.annotation;

WPDescriptionAnnotation *descAnno=[[WPDescriptionAnnotation alloc]init];

descAnno.tuangou=anno.tuangou;

[mapView addAnnotation:descAnno];

}

我们一般在项目中添加大头针,是有数据模型的。先把这个数据模型赋值给大头针,然后再添加。当然,大头针需要在自己的类中设置setTuangou也就是设置数据模型。

for (WPTuanGou *tuan in self.tuangous) {

WPAnnotation *anno=[[WPAnnotation alloc]init];

anno.tuangou=tuan;

[self.mapView addAnnotation:anno];

}

我们一般在项目中,都是把模型和大头针,当做参数在不同的对象之间传递。

(5)导航划线

#import "ViewController.h"

#import

#import

#import "WPAnnotation.h"

@interface ViewController ()

@property (weak, nonatomic) IBOutlet MKMapView *mapView;

@property(nonatomic,strong) CLGeocoder *geocoder;

@end

@implementation ViewController

-(CLGeocoder *)geocoder{

if (_geocoder==nil) {

_geocoder=[[CLGeocoder alloc]init];

}

return _geocoder;

}

- (void)viewDidLoad {

[super viewDidLoad];

self.mapView.delegate=self;

NSString *add1=@"广州";

NSString *add2=@"北京";

//这个方法只能生效1个,所以不能分开写

[self.geocoder geocodeAddressString:add1 completionHandler:^(NSArray *placemarks, NSError *error) {

if (error) return;

CLPlacemark *fromPm=[placemarks firstObject];

[self.geocoder geocodeAddressString:add2 completionHandler:^(NSArray *placemarks, NSError *error) {

CLPlacemark *toPm=[placemarks firstObject];

[self addLineFrom:fromPm to:toPm];

}];

}];

}

-(void)addLineFrom:(CLPlacemark *)fromPm to:(CLPlacemark *)toPm{

//添加2个大头针

WPAnnotation *anno0=[[WPAnnotation alloc]init];

anno0.coordinate=fromPm.location.coordinate;

[self.mapView addAnnotation:anno0];

WPAnnotation *anno1=[[WPAnnotation alloc]init];

anno1.coordinate=toPm.location.coordinate;

[self.mapView addAnnotation:anno1];

//设置方向请求

MKDirectionsRequest *request=[[MKDirectionsRequest alloc]init];

//设置起点终点

MKPlacemark *sourcePm=[[MKPlacemark alloc]initWithPlacemark:fromPm];

request.source=[[MKMapItem alloc]initWithPlacemark:sourcePm];

MKPlacemark *destiPm=[[MKPlacemark alloc]initWithPlacemark:toPm];

request.destination=[[MKMapItem alloc]initWithPlacemark:destiPm];

//定义方向对象

MKDirections *dirs=[[MKDirections alloc]initWithRequest:request];

//计算路线

[dirs calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) {

NSLog(@"总共有%lu条线路",(unsigned long)response.routes.count);

for (MKRoute *route in response.routes) {

[self.mapView addOverlay:route.polyline];

}

}];

}

//划线就是添加路径,就是添加遮盖

-(MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id)overlay{

MKPolylineRenderer *renderer=[[MKPolylineRenderer alloc]initWithOverlay:overlay];

renderer.strokeColor=[UIColor redColor];

return renderer;

}

@end

还有一种方式创建导航,即利用MKMapItem:

MKMapItem *from=[[MKMapItem alloc]initWithPlacemark:[[MKPlacemark alloc] initWithPlacemark:fromPm]];

MKMapItem *to=[[MKMapItem alloc]initWithPlacemark:[[MKPlacemark alloc] initWithPlacemark:toPm]];

NSMutableDictionary *options=[NSMutableDictionary dictionary];

options[MKLaunchOptionsDirectionsModeKey]=MKLaunchOptionsDirectionsModeDriving;

options[MKLaunchOptionsShowsTrafficKey]=@YES;

[MKMapItem openMapsWithItems:@[from,to] launchOptions:options];

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容