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