Senior进阶
地图
地图的简介
在移动互联网时代,移动app能解决用户的很多生活琐事,比如导航:去任意陌生的地方
周边:找餐馆、找酒店、找银行、找电影院
手机软件:微信摇一摇、QQ附近的人、微博、支付宝等
在上述应用中,都用到了地图和定位功能,在iOS开发中,要想加入这两大功能,必须基于两个框架进行开发
Map Kit:用于地图展示
Core Location:用于地理定位
CoreLocation框架的使用
导入框架(iOS5.0之后不再需要)
导入头文件
#import<CoreLocation/CoreLocation.h>
CoreLocation框架使用须知
CoreLocation框架所有数据类型的前缀都是CL
CoreLocation中使用CLLocationManager对象来做用户定位
CLLocationManager的常用操作
//开始用户定位
- (void)startUpdatingLocation;
- //停止用户定位
- (Void)stopUpdatingLocation;
//当调用了startUpdatingLocation方法后,就开始不断地定位用户的位置,会频繁地调用下面的代理方法
- (Void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations;
//参数location中的元素对象是CLLocation对象
//每每多少米定位一次
@proprety(assign,nonatomic)CLLocationDistance distanceFilter;
//定位精确度(越精确就越耗电)
@proprety(assign,nonatomic)CLLocationAccuracy desiredAccuracy;
CLLocatioAccuracy
最佳导航
kCLLcationAccuracyBestForNavigation
kCLLocationAccuracyBest; 最精度
kCLLocationAccuracyNearestTenMeters; 10米
kCLLocationAccuracyHundredMeters; 100米
kCLLocationAccuracyKilometer; 1000米
kCLLocationAccuracyThreeKilometers; 3000米
实现定位只需要下面几步
1.创建管理者对象
self.manager = [CLLocationManager alloc]init];
2.设置代理
self.manager.delegate = self;
3.开启定位
[self.manager startUpdatingLocation];
//注意:从iOS7之后,苹果在保护用户隐私方面做了很大的加强,以下操作都必须经过用户批准授权;
1.要想获得用户的位置和访问用户的通讯录、日历、相机、相册等等都需要用户来手动授权。
2.当想访问用户的隐私信息时,系统会自动弹出一个对话框让用户授权
4.请求授权(授权方式根据实际情况进行选择)
/请求授权
[self,manager requestAlwaysAuthorization];//请求前台和后台定位
[self.manager requestWhenInUseAuthorization];//请求后台定位
//用户隐私的保护
开发者可以在Info.plist中设置NSLocationUSageDescription说明定位的目的
(Privacy-Location Usage Description)
一旦用户选择了“Don’t Allow”,意味着你的应用以后就无法使用定位功能为了严谨期间,最好在使用定位功能之前判断当前应用的定位功能是否可用
CLLocationManager有个类方法可以判断当前应用的定位功能是否可用
+(BOOL)locationServicesEnabled;
CLLocation
CLLocation用来表示缪戈位置的地理信息,比如经纬度、海发等等
//经纬度
@property(nomatomic strong)CLLocationCoordinate2D coordinate;
//海拔
@property(nonatomic strong)CLLocationDistace altitude;
//路线,航线(取值范围是0.0 - 359.9, 0.0代表正北方向)
@property(nonatomic strong)CLLocationDirection course;
CLLocation
//行走速度 (单位是m/s)
@property(nonatomic strong)CLLcationSpeed speed;
//此方法可以计算2个位置(CLLocation)之间的距离
- (CLLocationDistacance)idstanceFromLocation:(const CLLocation *)location
北京的经纬度是:北纬40°,东经116°
大连的经纬度是:北纬39°,东经121°
郑州的经纬度是:北纬34°,东经113°
上海的经纬度是:北纬31°,东经121°
广州的经纬度是:北纬23°,东经113°
西安的经纬度是:北纬34°,东经108
使用CLGeocoder可以完成“地理编码”和“反地理编码”
地理编码:根据给定的地名,获得具体的位置信息(比如经纬度、地址的全程等)
反地理编码:根据给定的经纬度,获得具体的位置信息
//地理编码方法
- (void)getAddressByLongitite:(CLLocationDegrees)longitude Latitude:(CLLocationDegrees)latitude {
- }
//反地理编码方法
-(void)reverseGeocodeLocation:loaction completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
}
CLGeocodeCompletionHandler
当地理编码/反地理编码完成时,就会调用CLGeocodeCompletionHanler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
}
block包含2和参数
error:当编码出错时(比如编码不出具体的信息)2.其错误信息会包含在error中
place marks:里面装着CLPlacemark对象
CLOlacemark的字面意思是地标,封装详细的地址位置信息
//地理位置
@property(nonatomic,strong)CLLocation *location;
//区域
@property(nonatomic,strong)CLRegion *region;
//详细的地址信息
@property(nonatomic,strong)NSDictionary *addressDictionary;
//地址名称
@property (nontomic ,strong)NSString *name;
//地点名称
@property(nonatomic ,strong)NSString *locality;
//CoreLocation框架中的CLLocationManager//第一步:引入库的头文件#import@interface ViewController () //定位管理器@property (nonatomic,strong)CLLocationManager *manager;@property(nonatomic,strong)CLGeocoder *geocoder;@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) { if ([CLLocationManager authorizationStatus]!=kCLAuthorizationStatusAuthorizedWhenInUse) { /* 定位服务授权状态,返回枚举类型: kCLAuthorizationStatusNotDetermined: 用户尚未做出决定是否启用定位服务 kCLAuthorizationStatusRestricted: 没有获得用户授权使用定位服务,可能用户没有自己禁止访问授权 kCLAuthorizationStatusDenied :用户已经明确禁止应用使用定位服务或者当前系统定位服务处于关闭状态 kCLAuthorizationStatusAuthorizedAlways: 应用获得授权可以一直使用定位服务,即使应用不在使用状态 kCLAuthorizationStatusAuthorizedWhenInUse: 使用此应用过程中允许访问定位服务 */ //在授权请求之前需要在inforPlist中设置 //请求授权 [self.manager requestWhenInUseAuthorization]; } } //初始化对象 self.geocoder = [[CLGeocoder alloc]init]; //根据地名获取经纬度// [self getCoordinateByAdress:@"北京"]; //根据经纬度反编码取出地名 // [self getAddressByLongitite:113.6 Latitude:34.64];//郑州市 // [self getAddressByLongitite:115 Latitude:34.2];//老人家// [self getAddressByLongitite:115.15 Latitude:34.4];//自己家 [self getAddressByLongitite:114.1 Latitude:32.41]; //计算两点之间的距离 [self distance]; // 第三步:设置管理器的代理和相关属性 self.manager.delegate = self; //设置精度 self.manager.desiredAccuracy = 100; //设置最小更新距离 self.manager.distanceFilter = 100; //第四步:开启定位 [self.manager startUpdatingLocation]; }#pragma mark - 计算两点之间的距离- (void)distance { // 北京的经纬度是:北纬40°,东经116°// 大连的经纬度是:北纬39°,东经121° //创建位置1:// CLLocation *locationBeijing = [[CLLocation alloc] initWithLatitude:40 longitude:116]; CLLocation *locationHome = [[CLLocation alloc] initWithLatitude:34.4 longitude:115.15]; //创建位置2// CLLocation *locationDalian = [[CLLocation alloc] initWithLatitude:39 longitude:121]; CLLocation *locationHome2 = [[CLLocation alloc] initWithLatitude:34.2 longitude:115]; // CLLocationDistance distance = [locationBeijing distanceFromLocation:locationDalian]; CLLocationDistance distance = [locationHome distanceFromLocation:locationHome2]; NSLog(@"自己家到ta家的距离=%f",distance); // NSLog(@"北京到大连的距离=%f",distance); }#pragma mark - 根据经纬度获取地址- (void)getAddressByLongitite:(CLLocationDegrees)longitude Latitude:(CLLocationDegrees)latitude { //反编码 //创建CLLcation CLLocation *loaction = [[CLLocation alloc] initWithLatitude:latitude longitude:longitude]; [_geocoder reverseGeocodeLocation:loaction completionHandler:^(NSArray * _Nullable placemarks, NSError * _Nullable error) { NSDictionary *dic = placemarks.firstObject.addressDictionary; NSLog(@"反编码地理位置信息:%@",dic); NSLog(@"%@",error); }]; }- (void)getCoordinateByAdress:(NSString *)address { [_geocoder geocodeAddressString:address completionHandler:^(NSArray * _Nullable placemarks, NSError * _Nullable error) { //根据返回的地标,取出第一个位置(地标的位置很多) CLPlacemark *mark = placemarks.firstObject; //根据地标得到location CLLocation *location = mark.location; //根据location获取区域 CLRegion *region = mark.region; //获取字典信息 NSDictionary *addressDic = mark.addressDictionary; NSLog(@"地标位置:%@,区域:%@,反编码地理位置信息:%@",location,region,addressDic); }];}#pragma mark -CLLocationManagerDelegate的代理方法//这个代理方法是定位成功知乎开始更新位置信息,只要移动设置的最小距离之后就开始也开始走这个方法- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { //获取最后一次的位置 CLLocation *location = locations.lastObject; CLLocationCoordinate2D coordinate = location.coordinate; NSLog(@"经度%f,纬度%f,海拔%f,航向%f,速度%f",coordinate.longitude,coordinate.latitude,location.altitude,location.course,location.speed); //为了节省电源,如果不适用定位,需要把定位关掉 [self.manager stopUpdatingLocation]; }//定位失败了- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error { NSLog(@"点位失败了"); }
#import "ViewController.h"//引入框架#import#import #import "MyAnnation.h"@interface ViewController () ///定位管理器@property(nonatomic,strong)CLLocationManager *locationManager;///显示地图的视图@property (nonatomic,strong)MKMapView *mapView;@end@implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. [self createMapView];}#pragma mark - 创建视图- (void)createMapView { //创建地图,并添加到当前视图上 self.mapView = [[MKMapView alloc] initWithFrame:[UIScreen mainScreen].bounds]; [self.view addSubview:self.mapView]; //设置代理 _mapView.delegate = self; //定位 self.locationManager = [[CLLocationManager alloc] init]; if (![CLLocationManager locationServicesEnabled]) { NSLog(@"当前设备定位不可用"); NSURL * url = [NSURL URLWithString:@"prefs:root=privacy"]; [[UIApplication sharedApplication]openURL:url]; } if ([CLLocationManager authorizationStatus]!= kCLAuthorizationStatusAuthorizedWhenInUse) { [self.locationManager requestWhenInUseAuthorization]; } //设置地图的定位追踪 _mapView.userTrackingMode = MKUserTrackingModeFollow; //设置地图的显示类型 _mapView.mapType = MKMapTypeStandard; //添加大头针 [self addAnnaotation];}#pragma mark - 添加大头针- (void)addAnnaotation{ //设置位置 CLLocationCoordinate2D location1 = CLLocationCoordinate2DMake(40, 116); MyAnnation *annotation = [[MyAnnation alloc] init]; annotation.coordinate = location1; annotation.title = @"北京"; annotation.subtitle = @"京"; #warning 添加代码 annotation.image = [UIImage imageNamed:@"222.jpg"]; [_mapView addAnnotation:annotation]; CLLocationCoordinate2D location2 = CLLocationCoordinate2DMake(39, 121); MyAnnation *annotation1 = [[MyAnnation alloc] init]; annotation1.coordinate =location2; annotation1.title = @"大连"; annotation1.subtitle = @"连"; annotation1.image = [UIImage imageNamed:@"222.jpg"]; [_mapView addAnnotation:annotation1]; CLLocationCoordinate2D location3 = CLLocationCoordinate2DMake(34, 113); MyAnnation *annotation2 =[[MyAnnation alloc] init]; annotation2.coordinate = location3; annotation2.title = @"郑州"; annotation2.subtitle = @"州"; annotation2.image = [UIImage imageNamed:@"222.jpg"]; [_mapView addAnnotation:annotation2]; }#pragma mark - 代理方法- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation { }#pragma mark - 实现自定义大头针视图的代理方法//显示大头针的时候才会调用的- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id )annotation { //判断是否是当前自低昂一的大头针类 if ([annotation isKindOfClass:[MyAnnation class]]) { //先定义一个重用标识 static NSString *identifier = @"AnnotationOne"; MKAnnotationView *annotationView = [_mapView dequeueReusableAnnotationViewWithIdentifier:identifier]; if (!annotationView) { annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier]; //允许用户交互 annotationView.canShowCallout = YES; //设置想抢个大头针的头偏移量 annotationView.calloutOffset = CGPointMake(0, 1); //设置详情的左视图 annotationView.leftCalloutAccessoryView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"111.jpg"]]; } //修改大头针视图 annotationView.annotation = annotation; annotationView.image = ((MyAnnation *)annotation).image; return annotationView; }else { return nil; } }@end