标签:
一、地图的简介
二、地图定位(CoreLocation框架,地理编码与反地理编码)
1、CoreLocation框架的使用
2、用户隐私的保护
// 引入库的头文件 #import <CoreLocation/CoreLocation.h> // 遵守协议 @interface ViewController ()<CLLocationManagerDelegate> /// 定位管理器 @property (nonatomic, strong) CLLocationManager *manager; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. // 定位的步骤 // 第一步:初始化定位管理器 self.manager = [[CLLocationManager alloc] init]; // 第二步:进行隐私的判断并授权 // 进行隐私的判断 if (![CLLocationManager locationServicesEnabled ]) { NSLog(@"是否前往隐私"); } // 根据状态进行授权(系统当前版本的判断) if ([UIDevice currentDevice].systemVersion.integerValue >= 8.0) { // 判断授权状态 /* 定位服务授权状态,返回枚举类型: kCLAuthorizationStatusNotDetermined: 用户尚未做出决定是否启用定位服务 kCLAuthorizationStatusRestricted: 没有获得用户授权使用定位服务,可能用户没有自己禁止访问授权 kCLAuthorizationStatusDenied :用户已经明确禁止应用使用定位服务或者当前系统定位服务处于关闭状态 kCLAuthorizationStatusAuthorizedAlways: 应用获得授权可以一直使用定位服务,即使应用不在使用状态 kCLAuthorizationStatusAuthorizedWhenInUse: 使用此应用过程中允许访问定位服务 */ if ([CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorizedWhenInUse) { // 在授权请求之前需要在info.plist中设置允许定位的内容:NSLocationWhenInUseUsageDescription // 请求授权 [self.manager requestWhenInUseAuthorization]; } } // 第三步:设置管理器的代理 self.manager.delegate = self; // 设置精确度CLLocationAccuracy 是一个枚举值
/*
最佳导航
kCLLocationAccuracyBestForNavigation
最精准
kCLLocationAccuracyBest;
10米
kCLLocationAccuracyNearestTenMeters;
百米
kCLLocationAccuracyHundredMeters;
千米
kCLLocationAccuracyKilometer;
3千米
kCLLocationAccuracyThreeKilometers;
*/ self.manager.desiredAccuracy = kCLLocationAccuracyHundredMeters; // 设置最小更新距离(单位:米) self.manager.distanceFilter = 10; // 开启定位 [self.manager startUpdatingLocation]; } #pragma mark - CLLocationManagerDelegate代理方法 /* 注意: 1.定位频率和定位精度并不应当越精确越好,需要视实际情况而定,因为越精确越耗性能,也就越费电。 2.定位成功后会根据设置情况频繁调用-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations方法,这个方法返回一组地理位置对象数组,每个元素一个CLLocation代表地理位置信息(包含经度、纬度、海报、行走速度等信息),之所以返回数组是因为有些时候一个位置点可能包含多个位置。 3.使用完定位服务后如果不需要实时监控应该立即关闭定位服务以节省资源。 4.除了提供定位功能,CLLocationManager还可以调用startMonitoringForRegion:方法对指定区域进行监控。 */ // 定位成功之后开始更新位置信息,只要移动设置的最小距离之后也开始走这个方法 - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations { // 获取最后一次的位置(经纬度)
//CLLocation用来表示某个位置的地理信息,比如经纬度、海拔等等
// 经纬度
@property(readonly, nonatomic) CLLocationCoordinate2D coordinate;
// 海拔
@property(readonly, nonatomic) CLLocationDistance altitude;
// 路线,航向(取值范围是0.0° ~ 359.9°,0.0°代表正北方向)
@property(readonly, nonatomic) CLLocationDirection course;
// 行走速度(单位是m/s)
@property(readonly, nonatomic) CLLocationSpeed speed;
// 此方法可以计算2个位置(CLLocation)之间的距离
- (CLLocationDistance)distanceFromLocation:(const CLLocation *)location
CLLocation *location = locations.lastObject; CLLocationCoordinate2D coordinate = location.coordinate; NSLog(@"**********latitude = %f**********, **********longitude = %f**********, **********altitude = %f**********, 航向 = %f, 行走速度 = %f", coordinate.latitude, coordinate.longitude, locations.lastObject.altitude, locations.lastObject.course, locations.lastObject.speed); // 为了节省电源,如果不适用定位,需要把定位关掉 [self.manager stopUpdatingLocation]; } // 定位失败 - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error { NSLog(@"定位失败"); }
3、地理编码与地理反编码
// 地理位置 @property (nonatomic, readonly) CLLocation *location; // 区域 @property (nonatomic, readonly) CLRegion *region; // 详细的地址信息 @property (nonatomic, readonly) NSDictionary *addressDictionary; // 地址名称 @property (nonatomic, readonly) NSString *name; // 地点名称 @property (nonatomic, readonly) NSString *locality;
@interface ViewController ()<CLLocationManagerDelegate> /// CLGeocoder能进行地理位置的编码和反编码 @property (nonatomic, strong) CLGeocoder *geocoder; @end - (void)viewDidLoad { // 初始化对象 self.geocoder = [[CLGeocoder alloc] init]; // 根据地名获取经纬度 [self getCoordinateByAddress:@"北京"]; // 根据经纬度反编码取出地名 [self getAddressByLongitude:116 Latitude:40]; // 计算两个位置之间的距离 [self distance]; } #pragma mark - 根据地名获取相关的信息 - (void)getCoordinateByAddress:(NSString *)address { // 编码方法 [self.geocoder geocodeAddressString:address completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) { NSLog(@"count1111 = %ld", placemarks.count); for (int i = 0; i < placemarks.count; i++) { // 根据返回的地标,取出第一个位置(地标的位置很多) CLPlacemark *mark = placemarks[i]; // 根据地标得到location CLLocation *location = mark.location; // 根据location获取区域 CLRegion *region = mark.region; // 获取字典信息 NSDictionary *addressDic = mark.addressDictionary; NSLog(@"地标 = %@,区域 = %@,字典 = %@",location,region,addressDic); } }]; } #pragma mark - 根据经纬度反编码出地名 - (void)getAddressByLongitude:(CLLocationDegrees)longitude Latitude:(CLLocationDegrees)latitude { // 反编码 // 创建CLLocation CLLocation *location = [[CLLocation alloc] initWithLatitude:latitude longitude:longitude]; [self.geocoder reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) { NSDictionary *dict = placemarks.lastObject.addressDictionary; NSLog(@"count= %ld", placemarks.count); NSLog(@"dic = %@", dict); }]; } #pragma mark - 计算两个位置之间的距离 - (void)distance { /* 北京的经纬度是 北纬40,东经116 大连的:北纬39,东经121 */ // 创建位置1 CLLocation *locationBeiJing = [[CLLocation alloc] initWithLatitude:40 longitude:116]; // 创建位置2 CLLocation *locationDaLian = [[CLLocation alloc] initWithLatitude:39 longitude:121]; CLLocationDistance distance = [locationBeiJing distanceFromLocation:locationDaLian]; NSLog(@"北京到大连的距离:%f", distance); }
三、地图显示(MapKit框架)
1、MapKit框架的使用
2、跟踪显示用户的位置
3、地图的类型
4、MKMapView的代理
// 一个位置更改默认只会调用一次,不断监测用户的当前位置时每次都会调用这个方法,把用户的最新位置(userLocation参数)传进来. - (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation; // 地图的显示区域即将发生改变的时候调用 - (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated; // 地图的显示区域已经发生改变的时候调用 - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated;
5、MKUserLocation
// 显示在大头针上的标题 @property (nonatomic, copy) NSString *title; // 显示在大头针上的子标题 @property (nonatomic, copy) NSString *subtitle; // 地理位置信息(大头针钉在什么地方) @property (readonly, nonatomic) CLLocation *location;
6、设置地图的显示
// 设置地图的中心点位置 @property (nonatomic) CLLocationCoordinate2D centerCoordinate; -(void)setCenterCoordinate: (CLLocationCoordinate2D)coordinate animated:(BOOL)animated; @property (nonatomic) MKCoordinateRegion region; - (void)setRegion:(MKCoordinateRegion)region animated:(BOOL)animated; //MKCoordinateRegion是一个用来表示区域的结构体,定义如下 typedef struct { CLLocationCoordinate2D center; // 区域的中心点位置 MKCoordinateSpan span; // 区域的跨度 } MKCoordinateRegion; MKCoordinateSpan的定义 typedef struct { CLLocationDegrees latitudeDelta; // 纬度跨度 CLLocationDegrees longitudeDelta; // 经度跨度 } MKCoordinateSpan;
7、大头针
8、代码示例:
#import "ViewController.h" //引入框架 #import <MapKit/MapKit.h> #import <CoreLocation/CoreLocation.h> #import "MyAnnotation.h" @interface ViewController ()<MKMapViewDelegate> /// 定位管理器 @property (nonatomic, strong) CLLocationManager *manager; /// 显示地图的视图 @property (nonatomic, strong) MKMapView *mapView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // 创建视图 [self createMapView]; } #pragma mark - 创建视图 - (void)createMapView { // 创建地图并添加到当前视图上 self.mapView = [[MKMapView alloc] initWithFrame:[UIScreen mainScreen].bounds]; [self.view addSubview:self.mapView]; // 设置代理 self.mapView.delegate = self; // 定位 self.manager = [[CLLocationManager alloc] init]; if (![CLLocationManager locationServicesEnabled]) { NSLog(@"当前设备定位不可用"); } if ([CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorizedWhenInUse) { [self.manager requestWhenInUseAuthorization]; } // 设置地图的定位追踪 self.mapView.userTrackingMode = MKUserTrackingModeFollow; // 设置地图的显示类型 self.mapView.mapType = MKMapTypeStandard; // 添加大头针 [self addAnnotation]; } #pragma mark - 添加大头针 - (void)addAnnotation { // 设置位置 CLLocationCoordinate2D loaction1 = CLLocationCoordinate2DMake(40, 116); MyAnnotation *annotation = [[MyAnnotation alloc] init]; annotation.coordinate = loaction1; annotation.title = @"北京"; annotation.subtitle = @"北京市"; // 大连 CLLocationCoordinate2D location2 = CLLocationCoordinate2DMake(39, 121); MyAnnotation *annotation2 = [[MyAnnotation alloc] init]; annotation2.coordinate = location2; annotation2.title = @"大连"; annotation2.subtitle = @"大连市"; // 上海 CLLocationCoordinate2D location3 = CLLocationCoordinate2DMake(31.23, 121.47); MyAnnotation *annotation3 = [[MyAnnotation alloc] init]; annotation3.coordinate = location3; annotation3.title = @"上海"; annotation3.subtitle = @"上海市"; [self.mapView addAnnotations:@[annotation, annotation2, annotation3]]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end
大头针模型:
@interface MyAnnotation : NSObject<MKAnnotation> // 重写协议中的三个属性 // 通常会重写协议中coordinate(标记位置)、title(标题)、subtitle(子标题)三个属性 @property (nonatomic) CLLocationCoordinate2D coordinate; @property (nonatomic, copy) NSString *title; @property (nonatomic, copy) NSString *subtitle; @end
四、自定义大头针
//MKAnnotationView的属性 // 大头针模型 @property (nonatomic, strong) id <MKAnnotation> annotation; // 显示的图片 @property (nonatomic, strong) UIImage *image; // 是否显示标注 @property (nonatomic) BOOL canShowCallout; // 标注的偏移量 @property (nonatomic) CGPoint calloutOffset; // 是否显示标注 @property (nonatomic) BOOL canShowCallout; // 标注的偏移量 @property (nonatomic) CGPoint calloutOffset; // MKPinAnnotationView是MKAnnotationView的子类 // MKPinAnnotationView比MKAnnotationView多了2个属性 // 大头针颜色 @property (nonatomic) MKPinAnnotationColor pinColor; // 大头针第一次显示时是否从天而降 @property (nonatomic) BOOL animatesDrop;
#pragma mark - 实现自定义大头针视图的代理方法 // 显示大头针的时候才会调用的 - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation { // 判断是否是当前自定义的大头针类 if ([annotation isKindOfClass:[MyAnnotation class]]) { // 先定义一个重用标识 static NSString *identifier = @"AnnotationOne"; MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:identifier]; if (!annotationView) { annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier]; // 允许用户交互 annotationView.canShowCallout = YES; // 设置图片 annotationView.image = [UIImage imageNamed:@"eye"]; // 设置详情和大头针偏移量 annotationView.calloutOffset = CGPointMake(0, 3); // 设置详情的左视图 annotationView.leftCalloutAccessoryView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Y0N[2Z@P[]SRYYA@I0CNNTO.jpg"]]; } return annotationView; } else { return nil; } }
标签:
原文地址:http://www.cnblogs.com/soley/p/5547718.html