有关MapView的显示和定位在上一节已经说明,这一节说明如何在地图上放置大头针,以及设置点击大头针的视图。
【系统默认大头针】
mapView上放置大头针的方法是调用其addAnnotation:方法,需要注意的是,传入的是模型而不是大头针视图。
- (void)addAnnotation:(id <MKAnnotation>)annotation;通过这个方法,我们可以清楚的看到,annotation模型需要遵循MKAnnotation协议,我们打开这个协议,可以看到如下的内容:
@protocol MKAnnotation <NSObject> // Center latitude and longitude of the annotation view. // The implementation of this property must be KVO compliant. @property (nonatomic, readonly) CLLocationCoordinate2D coordinate; @optional // Title and subtitle for use by selection UI. @property (nonatomic, readonly, copy) NSString *title; @property (nonatomic, readonly, copy) NSString *subtitle; // Called as a result of dragging an annotation view. - (void)setCoordinate:(CLLocationCoordinate2D)newCoordinate NS_AVAILABLE(10_9, 4_0); @end因此我们应当定义一个模型,按照协议定义这些属性,其中coordinate是必须定义的,因为大头针必须有位置。
模型类遵循MKAnnocation协议,命名为MyAnnotation,如下:
#import <Foundation/Foundation.h> #import <MapKit/MapKit.h> @interface MyAnnotation : NSObject<MKAnnotation> /** * 大头针的位置 */ @property (nonatomic, assign) CLLocationCoordinate2D coordinate; /** * 大头针标题 */ @property (nonatomic, copy) NSString *title; /** * 大头针的子标题 */ @property (nonatomic, copy) NSString *subtitle; @end
#import "MyAnnotation.h" @implementation MyAnnotation @end
然后就可以通过定义模型,调用addAnnotation:方法添加一枚大头针,例如我们通过Button,随机添加一枚大头针:
- (IBAction)addPin:(id)sender { MyAnnotation *anno = [[MyAnnotation alloc] init]; anno.title = @"title"; anno.subtitle = @"subtitle"; CLLocationDegrees latitude = 36.821119 + arc4random_uniform(20); CLLocationDegrees longtitude = 116.750112 + arc4random_uniform(20); anno.coordinate = CLLocationCoordinate2DMake(latitude, longtitude); [self.mapView addAnnotation:anno]; }
其中的title和subtitle是点击大头针时显示的气泡上的标题和副标题。
大头针的显示原理和tableView显示cell是类似的,一旦调用addAnnotation:方法,就会调用mapView:viewForAnnotationView:方法,这个方法中应当从缓存池取出一个大头针视图,或者如果缓存池中没有新建一个大头针视图,然后返回。
与tableView的区别是,如果直接返回nil,则会按照系统的样式返回大头针。
需要注意的是,如果不返回nil,要对不同类型的大头针进行处理,不要忘了用户的位置指示圆点也属于一种大头针,如果只是单单的设置大头针,连用户位置也会是一颗针而不是圆点。
判断方法很简单,因为用户位置大头针由系统创建,因此传入的模型肯定不是我们自己的模型MyAnnotation,只要判断传入的模型是不是这个类,如果不是,则返回nil,代表按照系统默认样式,创建圆点。
要创建大头针,使用的是MKPinAnnotationView,如果使用MKAnnotationView,是不带图片的,无法直接显示。
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{ static NSString *ID = @"anno"; // 如果返回nil,系统会按照默认方式显示,如果自定义,是无法直接显示的,并且点击大头针之后不会显示标题,需要自己手动设置显示 // 如果想要直接显示,应该调用MKPinAnnotationView MKPinAnnotationView *annoView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:ID]; if (annoView == nil) { annoView = [[MKPinAnnotationView alloc] initWithAnnotation:nil reuseIdentifier:ID]; // 大头针属性 annoView.animatesDrop = YES; // 设置大头针坠落的动画 annoView.canShowCallout = YES; // 设置点击大头针是否显示气泡 annoView.calloutOffset = CGPointMake(0, 0); // 设置大头针气泡的偏移 // 设置大头针气泡的左右视图、可以为任意UIView annoView.leftCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeContactAdd]; annoView.rightCalloutAccessoryView = [[UISwitch alloc] init]; [annoView setPinColor:MKPinAnnotationColorPurple]; // 设置大头针颜色 } // 设置大头针的图片,如果是直接创建MKPin,则无效。 //annoView.image = [UIImage imageNamed:@"pin"]; annoView.annotation = annotation; // 如果是用户位置,应当显示默认的圆点而不是大头针,因此应当判断是否是MyAnnotation if(![annoView.annotation isKindOfClass:[MyAnnotation class]]){ return nil; } return annoView; }
【自定义大头针】
自定义大头针需要使用MKAnnotationView,自己指定image,没有坠落动画,其他没有区别。
(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{ static NSString *ID = @"anno"; // 如果返回nil,系统会按照默认方式显示,如果自定义,是无法直接显示的,并且点击大头针之后不会显示标题,需要自己手动设置显示 // 如果想要直接显示,应该调用MKPinAnnotationView MKAnnotationView *annoView = [mapView dequeueReusableAnnotationViewWithIdentifier:ID]; if (annoView == nil) { annoView = [[MKPinAnnotationView alloc] initWithAnnotation:nil reuseIdentifier:ID]; // 大头针属性 //annoView.animatesDrop = YES; // MKPinAnnotaionView才有效,设置大头针坠落的动画 annoView.canShowCallout = YES; // 设置点击大头针是否显示气泡 annoView.calloutOffset = CGPointMake(0, 0); // 设置大头针气泡的偏移 // 设置大头针气泡的左右视图、可以为任意UIView annoView.leftCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeContactAdd]; annoView.rightCalloutAccessoryView = [[UISwitch alloc] init]; //[annoView setPinColor:MKPinAnnotationColorPurple]; // MKPinAnnotaionView才有效,设置大头针的颜色 } // 设置大头针的图片 annoView.image = [UIImage imageNamed:@"pin"]; annoView.annotation = annotation; // 如果是用户位置,应当显示默认的圆点而不是大头针,因此应当判断是否是MyAnnotation if(![annoView.annotation isKindOfClass:[MyAnnotation class]]){ return nil; } return annoView; }
【MVC封装annotationView的注意点】
annotation要传入模型,在重写的set方法里,注意调用父类的set方法,先设置公共属性,再设置自己所特有的。
有一个细节,默认set方法的传入模型是id<MKAnnotaion>类型,在使用时还需要强转类型,为了方便,我们直接把类型改为MyAnnotation,因为OC在调用方法时发送的消息只包括方法名和冒号、描述,因此类型不属于方法名的一部分,可以修改。
- (void)setAnnotation:(MyAnnotation *)annotation{ [super setAnnotation:annotation]; // 设置特有的属性,例如图片、左右视图等。 }