標籤:
(1)自訂圖釘Annotation的樣式,也就是定義view,主要的方法是如下,傳遞一個圖釘annotation模型,然後返回一個MKAnnotationView,這個MKAnnotationView有一個image屬性,設定這個屬性,就能設定它的樣式了。
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{}
關鍵提示,這個MKAnnotationView和tableViewCell類似,可以迴圈利用,先從mapView中取,取不到再建立。
主要代碼:
#import "ViewController.h"#import <MapKit/MapKit.h>#import <CoreLocation/CoreLocation.h>#import "WPAnnotation.h"@interface ViewController ()<MKMapViewDelegate>@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); [email protected]"全聚德"; [email protected]"全北京最好的烤鴨店"; [email protected]"category_1"; [self.mapView addAnnotation:anno0]; WPAnnotation *anno1=[[WPAnnotation alloc]init]; anno1.coordinate=CLLocationCoordinate2DMake(39, 115); [email protected]"萬達影院"; [email protected]"全中國最頂尖的觀影聖地"; [email protected]"category_5"; [self.mapView addAnnotation:anno1];}-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{ static NSString *[email protected]"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 <Foundation/Foundation.h>#import <MapKit/MapKit.h>@interface WPAnnotation : NSObject<MKAnnotation>@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; [email protected]"全聚德"; [email protected]"來一隻鴨子,老闆!"; [self.mapView addAnnotation:anno];}-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{ static NSString *[email protected]"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<MKAnnotation>)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 <CoreLocation/CoreLocation.h>#import <MapKit/MapKit.h>#import "WPAnnotation.h"@interface ViewController ()<MKMapViewDelegate>@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 *[email protected]"廣州"; NSString *[email protected]"北京"; //這個方法只能生效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<MKOverlay>)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][email protected]; [MKMapItem openMapsWithItems:@[from,to] launchOptions:options];
【iOS開發-111】自訂圖釘Annotation以及2種導航劃線的方法介紹