自定義大頭針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];

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容