*** 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; }
** **要在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]; }