地图
准备工作
- 导入MapKit框架(iOS5之后不在需要程序员自己导入)
- 导入主头文件#import
- MapKit框架中所有的数据类型的前缀都是MK。
- MapKit有一个比较重要的UI控件:MKMapView,专门用于地图的显示
- 设置MKMapView的userTrackingModes属性可以跟踪显示用户的当前位置
typedef NS_ENUM(NSInteger, MKUserTrackingMode) {
MKUserTrackingModeNone = 0, // 不跟踪用户的位置
MKUserTrackingModeFollow, //跟踪并在地图上显示用户当前的位置
MKUserTrackingModeFollowWithHeading, //跟踪并在地图上显示用户当前的位置,地图会随着用户前进的方向进行旋转。
} NS_ENUM_AVAILABLE(NA, 5_0) __WATCHOS_PROHIBITED;
- 可以通过设置MKMapView的mapType设置地图的类型(mapType是一个枚举值)
typedef NS_ENUM(NSUInteger, MKMapType) {
MKMapTypeStandard = 0,//普通地图
MKMapTypeSatellite,//卫星云图
MKMapTypeHybrid,//普通地图覆盖于卫星云图之上
MKMapTypeSatelliteFlyover NS_ENUM_AVAILABLE(10_11, 9_0),//地形和建筑的三围模型
MKMapTypeHybridFlyover NS_ENUM_AVAILABLE(10_11, 9_0),显示道路和附加元素的Flyover
}
创建一个地图
- 在延展里声明一个地图的属性
@interface RootViewController ()
@property (strong, nonatomic)MKMapView *mapView;
@property (assign, nonatomic)CGRect frame;
@end
- 把这个属性写成懒加载并将它添加视图控制器的view上
-(MKMapView *)mapView{
if (!_mapView) {
_mapView = [[MKMapView alloc]initWithFrame:self.view.bounds];
[self.view addSubview:_mapView];
}return _mapView;
}
- 为了让地图适配屏幕的旋转,我们需要重写下面这个方法
这个方法的返回值是一个枚举类型,返回的是支持屏幕旋转的方向
typedef NS_OPTIONS(NSUInteger, UIInterfaceOrientationMask) {
UIInterfaceOrientationMaskPortrait//home键在下
UIInterfaceOrientationMaskLandscapeLeft//支持向左旋转
UIInterfaceOrientationMaskLandscapeRight//支持向右旋转
UIInterfaceOrientationMaskPortraitUpsideDown//支持上下
UIInterfaceOrientationMaskLandscape//支持左右同时旋转
UIInterfaceOrientationMaskAll//支持四个方向
UIInterfaceOrientationMaskAllButUpsideDown//支持上左右
}
-(UIInterfaceOrientationMask)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskAll;//让旋转支持所有方向
}
使用下面的这个方法,可以监测到屏幕的旋转,在这个我们徐亚我改变地图的位置信息。
在此之前我们需要现在viewDidLoad中获取到程序启动时的位置信息
-(void)viewDidLoad{
self.frame = self.view.frame;
}
-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:
(id)coordinator{
CGRect temp = CGRectMake(0, 0, 0, 0);
if (size.width > size.height) {
temp = CGRectMake(0, 0, self.frame.size.height, self.frame.size.width);
}else{
temp = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
}
self.mapView.frame = temp;
}
- 设置地图的跟踪属性,以及使用的地图类型
//用户位置追踪(用户位置追踪用于标记用户当前位置,此时会调用定位服务)
self.mapView.userTrackingMode = MKUserTrackingModeFollowWithHeading;
self.mapView.mapType = MKMapTypeStandard;//普通地图
self.mapView.delegate = self;//指定代理人,下面我们需要实现一些地图和大头针的下一方法。
完成以上的四步,我们就可以在我们的模拟器上看到地图了
下面我们需要在地图上设置它的另外一个属性,大头针。
地图的代理方法
- 当地图显示的位置发生改变,就会执行此代理方法。
-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation{
//将得到的location信息 反地理编码成位置名称。
NSLog(@"位置发生变化了");
CLGeocoder *geocoder = [[CLGeocoder alloc]init];
[geocoder reverseGeocodeLocation:userLocation.location completionHandler:^(NSArray * _Nullable placemarks, NSError * _Nullable error) {
CLPlacemark *newPlacemark = placemarks.lastObject;
//设置大头针的标题
userLocation.title = newPlacemark.country;
userLocation.subtitle = newPlacemark.name;
}];
}
- 地图上显示的区域即将发生改变的时候调用的方法
-(void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated{
NSLog(@"地图上显示的区域即将发生改变");
}
- 地图上的位置显示的区域已经发生改变的时候调用的方法。
-(void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated{
NSLog(@"地图上的位置显示的区域已经发生改变");
}
大头针
在iOS开发中经常会标记某个位置,需要使用地图标注,也就是大家俗称的“大头针”。在这里系统为我们提供了一个大头针的类MKPointAnnotation
系统的大头针
MKPointAnnotation *pointAnnotation = [[MKPointAnnotation alloc]init];
pointAnnotation.coordinate = CLLocationCoordinate2DMake(35, 108);//设置大头针的位置信息
/**
* 设置大头针的标题
*/
pointAnnotation.title = @"甘家寨";//主标题
pointAnnotation.subtitle = @"大牛夜市";//副标题
[self.mapView addAnnotation:pointAnnotation];//将大头针添加到地图上
自定义大头针
只要一个NSObject类实现MKAnnotation协议就可以作为一个大头针,通常会重写协议中coordinate(标记位置)、title(标题)、subtitle(子标题)三个属性,然后在程序中创建大头针对象并调用addAnnotation:方法添加大头针即可(之所以iOS没有定义一个基类实现这个协议供开发者使用,多数原因应该是MKAnnotation是一个模型对象,对于多数应用模型会稍有不同,例如后面的内容中会给大头针模型对象添加其他属性)。
#import
#import
@interface MyAnnotation : NSObject//遵循annotation协议
@property (assign, nonatomic)CLLocationCoordinate2D coordinate;//位置信息
@property (copy, nonatomic)NSString *title;//标题
@property (copy, nonatomic)NSString *subtitle;//副标题
@end
使用自定义的大头针
- (void)myannotation{
MyAnnotation *annotation = [[MyAnnotation alloc]init];
annotation.coordinate = CLLocationCoordinate2DMake(35, 107);
annotation.title = @"大雁塔";
annotation.subtitle = @"西安市";
[self.mapView addAnnotation:annotation];
}
自定义大头针的协议方法
每插入一个大头针,都会执行一次代理方法。
这个方法有点类似于tableView的重用机制,能有效的节约资源。
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:
(id)annotation{
MKPinAnnotationView *annotationView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:@"insert"];
if (!annotationView) {
annotationView = [[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:@"insert"];
}
if ([annotation isKindOfClass:[MyAnnotation class]]) {
annotationView.pinTintColor = [UIColor blackColor];//设置大头针的颜色
annotationView.animatesDrop = YES;//设置从天而降的效果
annotationView.canShowCallout = YES;//在点击大头针时是否显示标题
annotationView.leftCalloutAccessoryView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"2.jpeg"]];//设置大头针的左侧辅助视图
return annotationView;
}else{
return nil;//当前方法返回值为nil的时候大头针保持系统的样子
}
}