​ MapKit地图

1 MapKit基础使用

 *** Terminating app due to uncaught exception 'NSInvalidUnarchiveOperationException', reason: 'Could not instantiate class named MKMapView'

    如果storyboard中用到了地图, 必须手动导入框架

#import <MapKit/MapKit.h>
@interface ViewController ()<MKMapViewDelegate>
/**
 *  地图
 */
@property (weak, nonatomic) IBOutlet MKMapView *customMapView;
@property (nonatomic, strong) CLLocationManager *mgr;
/**
 *  地理编码对象
 */
@property (nonatomic ,strong) CLGeocoder *geocoder;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // 1.设置地图显示的类型
    /*
     typedef enum : NSUInteger {
     MKMapTypeStandard , 标准(默认)
     MKMapTypeSatellite ,卫星
     MKMapTypeHybrid 混合(标准 + 卫星)
     } MKMapType;
     */
    self.customMapView.mapType = MKMapTypeSatellite;
    
    
    //2.CoreLocation框架定位
    // 注意:在iOS8中, 如果想要追踪用户的位置, 必须自己主动请求隐私权限
    if ([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0) {
        // 主动请求权限
        self.mgr = [[CLLocationManager alloc] init];
        
        [self.mgr requestAlwaysAuthorization];
    }
    
    //3. 设置不允许地图旋转
    self.customMapView.rotateEnabled = NO;
    
    //4. 成为mapVIew的代理
    self.customMapView.delegate = self;
    
    //5. 如果想利用MapKit获取用户的位置, 可以追踪
    /*
     typedef NS_ENUM(NSInteger, MKUserTrackingMode) {
     MKUserTrackingModeNone = 0, 不追踪/不准确的
     MKUserTrackingModeFollow, 追踪
     MKUserTrackingModeFollowWithHeading, 追踪并且获取用的方向
     }
     */
    self.customMapView.userTrackingMode =  MKUserTrackingModeFollow;
    
    
}

#pragma MKMapViewDelegate
/**
 *  每次更新到用户的位置就会调用(调用不频繁, 只有位置改变才会调用)
 *  @param userLocation 大头针模型
 */
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
    /*
     地图上蓝色的点就称之为大头针
     大头针可以拥有标题/子标题/位置信息
     大头针上显示什么内容由大头针模型确定(MKUserLocation)
     */
    
    //1.设置大头针内容
    // 利用反地理编码获取位置之后设置标题
    [self.geocoder reverseGeocodeLocation:userLocation.location completionHandler:^(NSArray *placemarks, NSError *error) {
        CLPlacemark *placemark = [placemarks firstObject];
        NSLog(@"获取地理位置成功 name = %@ locality = %@", placemark.name, placemark.locality);
        userLocation.title = placemark.name;
        userLocation.subtitle = placemark.locality;
    }];
    
    
    //2.设置大头针显示范围
    // 移动地图到当前用户所在位置。
//    [self.customMapView setCenterCoordinate:userLocation.location.coordinate animated:YES];
    
    //3. 设置地图显示的区域,也会移动地图到当前用户所在位置
    // 获取用户的位置
    CLLocationCoordinate2D center = userLocation.location.coordinate;
    // 指定经纬度的跨度
    MKCoordinateSpan span = MKCoordinateSpanMake(0.009310,0.007812);
    // 将用户当前的位置作为显示区域的中心点, 并且指定需要显示的跨度范围
    MKCoordinateRegion region = MKCoordinateRegionMake(center, span);
    // 设置显示区域
    [self.customMapView setRegion:region animated:YES];
}


//- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated

/**
 *  地图的区域改变完成时调用。通常用来获取显示范围的经纬度。
 *  1度等于110km
 */
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
    NSLog(@"地图的区域改变完成时调用");
    
    // 0.119170 0.100000
    // 0.238531 0.200156
    // 0.009310 0.007812
    NSLog(@"%f %f", self.customMapView.region.span.latitudeDelta, self.customMapView.region.span.longitudeDelta);
}

#pragma mark - 懒加载
- (CLGeocoder *)geocoder
{
    if (!_geocoder) {
        _geocoder = [[CLGeocoder alloc] init];
    }
    return _geocoder;
}
2 自定义大头针
**
**要在1,基础使用的前提下自定义

//添加数据到模型中
- (IBAction)addAnno {
    // 创建大头针模型
    HMAnnotation *anno = [[HMAnnotation alloc] init];
    anno.title = @"传智";
    anno.subtitle = @"育新小区";
    CGFloat latitude = 36.821199 + arc4random_uniform(20);
    CGFloat longitude = 116.858776 + arc4random_uniform(20);
    anno.coordinate = CLLocationCoordinate2DMake(latitude , longitude);
    anno.icon = @"category_1";
    
    // 添加大头针
    [self.customMapView addAnnotation:anno];
    
    
    // 创建大头针模型
    HMAnnotation *anno2 = [[HMAnnotation alloc] init];
    anno2.title = @"传智2";
    anno2.subtitle = @"育新小区2";
    CGFloat latitude2 = 36.821199 + arc4random_uniform(20);
    CGFloat longitude2 = 116.858776 + arc4random_uniform(20);
    anno2.coordinate = CLLocationCoordinate2DMake(latitude2 , longitude2);
    anno2.icon = @"category_2";
    
    // 添加大头针
    [self.customMapView addAnnotation:anno2];
}



//添加多少次数据到annotation,就会调用多少次这个代理方法
#pragma MKMapViewDelegate
/**
 *  每次添加大头针就会调用(地图上有几个大头针就调用几次)
 *
 *  @param mapView    地图
 *  @param annotation 大头针模型
 *
 *  @return 大头针的view
 */
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{

    // 对用户当前的位置的大头针特殊处理,定位位置大头针不变
    // 注意: 如果return nil, 系统会按照自己默认的方式显示
    if ([annotation isKindOfClass:[HMAnnotation class]] == NO) {
        return nil;
    }
    
    static NSString *identifier = @"anno";
    
    /* 1.从缓存池中取
       2.如果缓存池中没有, 创建一个新的
         1>注意: 默认情况下MKAnnotationView是无法显示的,除非使用图标图片属性,否则想自定义大头针可以使用MKAnnotationView的子类MKPinAnnotationView
         2>.注意: 如果是自定义的大头针, 默认情况点击大头针之后是不会显示标题的, 需要我们自己手动设置显示,要设置annoView.canShowCallout = YES;
        
     //强制转换为子类
       MKPinAnnotationView *annoView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
     
     //两个MKPinAnnotationView的特有属性
       annoView.pinColor = MKPinAnnotationColorPurple; //设置大头针的颜色
        annoView.animatesDrop = YES;                   //设置大头针从天而降
    */
    
    
    MKAnnotationView *annoView = [mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
    if (annoView == nil) {
        annoView = [[MKPinAnnotationView alloc] initWithAnnotation:nil reuseIdentifier:identifier];
        annoView = [[MKAnnotationView alloc] initWithAnnotation:nil reuseIdentifier:identifier];

        
        // 设置大头针标题是否显示
        annoView.canShowCallout = YES;
        
        // 设置大头针标题显示的偏移位
        annoView.calloutOffset = CGPointMake(0, 0);
        
        // 设置大头针左边的辅助视图
        annoView.leftCalloutAccessoryView = [[UISwitch alloc] init];
        // 设置大头针右边的辅助视图
        annoView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeContactAdd];
      
    }
    
    // 设置大头针的图片
    // 注意: 如果你是使用的MKPinAnnotationView创建的自定义大头针, 那么设置图片无效, 因为系统内部会做一些操作, 覆盖掉我们自己的设置
    HMAnnotation *anno = (HMAnnotation *)annotation;
    annoView.image = [UIImage imageNamed:anno.icon];
    
    // 3.给大头针View设置数据
    annoView.annotation = annotation;
    
    // 4.返回大头针View
    return annoView;
    
}
//
/************以下方法是封装MKAnnotationView(没有涉及到它的子类MKPinAnnotationView),类似与tableView的cell*************/
#import "HMAnnotationView.h"
#import "HMAnnotation.h"    //数据模型

@implementation HMAnnotationView

//初始化
- (instancetype)initWithAnnotation:(id<MKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier
{
    if (self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier]) {
        // 初始化
        // 设置大头针标题是否显示
        self.canShowCallout = YES;
        
        // 设置大头针左边的辅助视图
        self.leftCalloutAccessoryView = [[UISwitch alloc] init];
        
        // 设置大头针右边的辅助视图
        self.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeContactAdd];
    }
    return self;
}

+ (instancetype)annotationViewWithMap:(MKMapView *)mapView
{
    static NSString *identifier = @"anno";
    
    // 1.从缓存池中取
    HMAnnotationView *annoView = (HMAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
    // 2.如果缓存池中没有, 创建一个新的
    if (annoView == nil) {
        
        annoView = [[HMAnnotationView alloc] initWithAnnotation:nil reuseIdentifier:identifier];
    }
    
    return annoView;
}

//- (void)setAnnotation:(id<MKAnnotation>)annotation
- (void)setAnnotation:(HMAnnotation *)annotation
{
    [super setAnnotation:annotation];
    
    //     处理自己特有的操作
    self.image = [UIImage imageNamed:annotation.icon];
    
}



转载于:https://my.oschina.net/u/2346786/blog/509326

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值