MapKit地圖

1 MapKit基礎使用

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

    若是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];
    
}
相關文章
相關標籤/搜索