(八十)MapKit放置系统默认大头针和自定义大头针

有关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];
   // 设置特有的属性,例如图片、左右视图等。
}


posted on 2015-07-22 19:56  张大大123  阅读(208)  评论(0编辑  收藏  举报

导航