(1)自定義大頭針Annotation的樣式禁灼,也就是定義view,主要的方法是如下轿曙,傳遞一個大頭針annotation模型弄捕,然后返回一個 MKAnnotationView,這個MKAnnotationView有一個image屬性导帝,設置這個屬性察藐,就能設置它的樣式了。
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id)annotation{
}
關鍵提示舟扎,這個MKAnnotationView和tableViewCell類似分飞,可以循環(huán)利用,先從mapView中取睹限,取不到再創(chuàng)建譬猫。
主要代碼:
#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];
//點擊大頭針出現(xiàn)信息(自定義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)如果我們加入追蹤用戶現(xiàn)有位置時
//追蹤用戶位置self.mapView.userTrackingMode=MKUserTrackingModeFollow;
發(fā)現(xiàn)會有如下報錯: [MKUserLocation icon]: unrecognized selector sent to instance 0x7f89baecab50
主要原因是,追蹤用戶位置的MKUserLocation也是一個大頭針(藍色發(fā)光的那個圈圈)叨恨,它也要經(jīng)過viewForAnnotation 這個代理方法返回自定義的大頭針柳刮,但是它是沒有icon屬性的,所以報錯。我們應該在viewForAnnotation中添加一個判斷:
//如果是系統(tǒng)自帶的大頭針秉颗,則返回默認的痢毒,否則下面要設置icon時會報錯,因為系統(tǒng)的大頭針沒有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];
//設置描述信息能點擊出現(xiàn)
annoView.canShowCallout=YES;
//設置顏色
annoView.pinColor=MKPinAnnotationColorGreen;
//設置第一次出現(xiàn)從天而降
annoView.animatesDrop=YES;
}
return annoView;
}
(4)自定義一個MKAnnotationView帅霜,并利用代理方法,監(jiān)聽大頭針的點擊呼伸,點擊后义屏,再彈出一個“大頭針”(只不過這個大頭針是自定義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];
}
我們一般在項目中添加大頭針澳叉,是有數(shù)據(jù)模型的。先把這個數(shù)據(jù)模型賦值給大頭針沐悦,然后再添加成洗。當然,大頭針需要在自己的類中設置setTuangou也就是設置數(shù)據(jù)模型藏否。
for (WPTuanGou *tuan in self.tuangous) {
WPAnnotation *anno=[[WPAnnotation alloc]init];
anno.tuangou=tuan;
[self.mapView addAnnotation:anno];
}
我們一般在項目中瓶殃,都是把模型和大頭針,當做參數(shù)在不同的對象之間傳遞副签。
(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
還有一種方式創(chuàng)建導航淆储,即利用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];