iOS地图定位【学习版】

首先要实现地图、导航功能,就需要我们先熟悉定位功能,在iOS中通过Core Location框架进行定位操作。Core Location自身可以单独使用,和地图开发框架MapKit完全是独立的,但是往往地图开发要配合定位框架使用。在Core Location中主要包含了定位、地理编码(包括反编码)功能。

由于目前苹果iOS系统最新版本为9.1,苹果自iOS8以后如果要使用定位服务,需要我们在plist文件中多添加两个字段,其实就是提示用户授权的用的,就是以下两个字段:

NSLocationWhenInUseUsageDescription当用户使用的允许NSLocationAlwaysUsageDescription总是允许

定位服务授权状态枚举类型说明:

//定位服务授权状态,返回枚举类型://kCLAuthorizationStatusNotDetermined: 用户尚未做出决定是否启用定位服务//kCLAuthorizationStatusRestricted: 没有获得用户授权使用定位服务,可能用户没有自己禁止访问授权//kCLAuthorizationStatusDenied :用户已经明确禁止应用使用定位服务或者当前系统定位服务处于关闭状态//kCLAuthorizationStatusAuthorizedAlways: 应用获得授权可以一直使用定位服务,即使应用不在使用状态//kCLAuthorizationStatusAuthorizedWhenInUse: 使用此应用过程中允许访问定位服务

获取当前位置

ViewController.m

#import"ViewController.h"#import@interfaceViewController()@property(nonatomic,strong)CLLocationManager*locationManager;@end@implementationViewController- (void)viewDidLoad {    [superviewDidLoad];//初始化locationManger管理器对象CLLocationManager*locationManager=[[CLLocationManageralloc]init];self.locationManager=locationManager;//判断当前设备定位服务是否打开if(![CLLocationManagerlocationServicesEnabled]) {NSLog(@"设备尚未打开定位服务");    }//判断当前设备版本大于iOS8以后的话执行里面的方法if([UIDevicecurrentDevice].systemVersion.floatValue >=8.0) {//持续授权[locationManager requestAlwaysAuthorization];//当用户使用的时候授权[locationManager requestWhenInUseAuthorization];    }//或者使用这种方式,判断是否存在这个方法,如果存在就执行,没有的话就忽略//if([locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]){//  [locationManager requestWhenInUseAuthorization];//}//设置代理locationManager.delegate=self;//设置定位的精度locationManager.desiredAccuracy=kCLLocationAccuracyBest;//设置定位的频率,这里我们设置精度为10,也就是10米定位一次CLLocationDistancedistance=10;//给精度赋值locationManager.distanceFilter=distance;//开始启动定位[locationManager startUpdatingLocation];}//当位置发生改变的时候调用(上面我们设置的是10米,也就是当位置发生>10米的时候该代理方法就会调用)- (void)locationManager:(CLLocationManager*)manager didUpdateLocations:(NSArray *)locations{//取出第一个位置CLLocation*location=[locations firstObject];NSLog(@"%@",location.timestamp);//位置坐标CLLocationCoordinate2Dcoordinate=location.coordinate;NSLog(@"经度:%f,纬度:%f,海拔:%f,航向:%f,速度:%f",coordinate.longitude,coordinate.latitude,location.altitude,location.course,location.speed);//如果不需要实时定位,使用完即使关闭定位服务//[_locationManager stopUpdatingLocation];}

2015-11-2913:02:48.380地图定位[1022:55837]2015-11-2905:02:06+00002015-11-2913:02:48.381地图定位[1022:55837]您的当前位置:经度:-116.206410,纬度:39.285834,海拔:0.000000,航向:-1.000000,速度:-1.0000002015-11-2913:02:48.383地图定位[1022:55837]2015-11-2905:02:48+00002015-11-2913:02:48.383地图定位[1022:55837]您的当前位置:经度:-116.206410,纬度:39.285834,海拔:0.000000,航向:-1.000000,速度:-1.0000002015-11-2913:03:03.081地图定位[1022:55837]2015-11-2905:03:03+00002015-11-2913:03:03.081地图定位[1022:55837]您的当前位置:经度:-116.306410,纬度:39.285834,海拔:0.000000,航向:-1.000000,速度:-1.0000002015-11-2913:03:34.226地图定位[1022:55837]2015-11-2905:03:34+00002015-11-2913:03:34.226地图定位[1022:55837]您的当前位置:经度:-116.406400,纬度:39.285834,海拔:0.000000,航向:-1.000000,速度:-1.0000002015-11-2913:03:57.659地图定位[1022:55837]2015-11-2905:03:57+00002015-11-2913:03:57.659地图定位[1022:55837]您的当前位置:经度:-116.506400,纬度:39.285834,海拔:0.000000,航向:-1.000000,速度:-1.000000

根据经纬度计算两地的距离

ViewController.m

#import"ViewController.h"#import@interfaceViewController()@property(nonatomic,strong)CLLocationManager*locationManager;@end@implementationViewController- (void)viewDidLoad {    [superviewDidLoad];//创建位置管理器CLLocationManager*locationManager=[[CLLocationManageralloc]init];self.locationManager=locationManager;//判断当前设备版本是否大于或等于8.0if([UIDevicecurrentDevice].systemVersion.floatValue >=8.0) {//持续授权//[locationManager requestAlwaysAuthorization];//使用期间授权[locationManager requestWhenInUseAuthorization];    }//iOS 9.0以后苹果提供的新属性if([UIDevicecurrentDevice].systemVersion.floatValue >9.0) {//是否允许后台定位locationManager.allowsBackgroundLocationUpdates=YES;    }//开始定位[locationManager startUpdatingLocation];//比较两点距离[selfcompareDistance];}//比较两地之间距离(直线距离)- (void)compareDistance{//北京 (116.3,39.9)CLLocation*location1=[[CLLocationalloc]initWithLatitude:39.9longitude:116.3];//郑州 (113.42,34.44)CLLocation*location2=[[CLLocationalloc]initWithLatitude:34.44longitude:113.42];//比较北京距离郑州的距离CLLocationDistancelocationDistance=[location1 distanceFromLocation:location2];//单位是m/s 所以这里需要除以1000NSLog(@"北京距离郑州的距离为:%f",locationDistance/1000);}

运行结果:

2015-11-2916:36:44.742测量两点间距离[1500:125741]北京距离郑州的距离为:657.622676

地理编码与反地理编码

地理编码:根据地址获得相应的经纬度以及详细信息

反地理编码:根据经纬度获取详细的地址信息(比如:省市、街区、楼层、门牌等信息)

地理编码与反地理编码用到得两个方法

//地理编码- (void)geocodeAddressString:(NSString*)addressString completionHandler:(CLGeocodeCompletionHandler)completionHandler;

//反地理编码- (void)reverseGeocodeLocation:(CLLocation*)location completionHandler:(CLGeocodeCompletionHandler)completionHandler;

地理编码的使用

ViewController.m

#import"ViewController.h"#import@interfaceViewController()//地址@property(weak,nonatomic)IBOutletUITextField*addressTextField;//经度@property(weak,nonatomic)IBOutletUITextField*longitudeTextField;//纬度@property(weak,nonatomic)IBOutletUITextField*latitudeTextField;//详细地址@property(weak,nonatomic)IBOutletUITextView*textView;@end@implementationViewController//地理编码- (IBAction)genocoder:(id)sender {//创建编码对象CLGeocoder*geocoder=[[CLGeocoderalloc]init];//判断是否为空if(self.addressTextField.text.length ==0) {return;    }    [geocoder geocodeAddressString:self.addressTextField.text completionHandler:^(NSArray * _Nullable placemarks,NSError* _Nullable error) {if(error!=nil|| placemarks.count==0) {return;        }//创建placemark对象CLPlacemark*placemark=[placemarks firstObject];//赋值经度self.longitudeTextField.text =[NSStringstringWithFormat:@"%f",placemark.location.coordinate.longitude];//赋值纬度self.latitudeTextField.text=[NSStringstringWithFormat:@"%f",placemark.location.coordinate.latitude];//赋值详细地址self.textView.text=placemark.name;    }];    }

反地理编码的使用

AntiEncoderController.m

#import"AntiEncoderController.h"#import@interfaceAntiEncoderController()//经度@property(weak,nonatomic)IBOutletUITextField*longitudeTextField;//纬度@property(weak,nonatomic)IBOutletUITextField*latitudeTextField;//详细地址@property(weak,nonatomic)IBOutletUITextView*textView;@end@implementationAntiEncoderController//反地理编码- (IBAction)AntiEncoder:(id)sender {//创建地理编码对象CLGeocoder*geocoder=[[CLGeocoderalloc]init];//创建位置CLLocation*location=[[CLLocationalloc]initWithLatitude:[self.latitudeTextField.text floatValue] longitude:[self.longitudeTextField.text floatValue]];//反地理编码[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray * _Nullable placemarks,NSError* _Nullable error) {//判断是否有错误或者placemarks是否为空if(error !=nil|| placemarks.count==0) {NSLog(@"%@",error);return;        }for(CLPlacemark*placemarkinplacemarks) {//赋值详细地址self.textView.text=placemark.name;        }            }];    }

mapView的使用

ViewController.m

#import"ViewController.h"#import@interfaceViewController()//mapView@property(weak,nonatomic)IBOutletMKMapView*mapView;@property(nonatomic,strong)CLLocationManager*locationManager;@end@implementationViewController- (void)viewDidLoad {    [superviewDidLoad];CLLocationManager*locationManager=[[CLLocationManageralloc]init];self.locationManager=locationManager;//请求授权[locationManager requestWhenInUseAuthorization];/*

    MKUserTrackingModeNone  不进行用户位置跟踪

    MKUserTrackingModeFollow  跟踪用户的位置变化

    MKUserTrackingModeFollowWithHeading  跟踪用户位置和方向变化

    *///设置用户的跟踪模式self.mapView.userTrackingMode=MKUserTrackingModeFollow;/*

    MKMapTypeStandard  标准地图

    MKMapTypeSatellite    卫星地图

    MKMapTypeHybrid      鸟瞰地图

    MKMapTypeSatelliteFlyover

    MKMapTypeHybridFlyover

    */self.mapView.mapType=MKMapTypeStandard;//实时显示交通路况self.mapView.showsTraffic=YES;//设置代理self.mapView.delegate=self;    }//跟踪到用户位置时会调用该方法- (void)mapView:(MKMapView*)mapView didUpdateUserLocation:(MKUserLocation*)userLocation{//创建编码对象CLGeocoder*geocoder=[[CLGeocoderalloc]init];//反地理编码[geocoder reverseGeocodeLocation:userLocation.location completionHandler:^(NSArray * _Nullable placemarks,NSError* _Nullable error) {if(error!=nil|| placemarks.count==0) {return;        }//获取地标CLPlacemark*placemark=[placemarks firstObject];//设置标题userLocation.title=placemark.locality;//设置子标题userLocation.subtitle=placemark.name;    }];    }//回到当前位置- (IBAction)backCurrentLocation:(id)sender {MKCoordinateSpanspan=MKCoordinateSpanMake(0.021251,0.016093);        [self.mapView setRegion:MKCoordinateRegionMake(self.mapView.userLocation.coordinate, span) animated:YES];}//当区域改变时调用- (void)mapView:(MKMapView*)mapView regionDidChangeAnimated:(BOOL)animated{//获取系统默认定位的经纬度跨度NSLog(@"维度跨度:%f,经度跨度:%f",mapView.region.span.latitudeDelta,mapView.region.span.longitudeDelta);}//缩小地图- (IBAction)minMapView:(id)sender {//获取维度跨度并放大一倍CGFloatlatitudeDelta =self.mapView.region.span.latitudeDelta *2;//获取经度跨度并放大一倍CGFloatlongitudeDelta =self.mapView.region.span.longitudeDelta *2;//经纬度跨度MKCoordinateSpanspan =MKCoordinateSpanMake(latitudeDelta, longitudeDelta);//设置当前区域MKCoordinateRegionregion =MKCoordinateRegionMake(self.mapView.centerCoordinate, span);        [self.mapView setRegion:region animated:YES];}//放大地图- (IBAction)maxMapView:(id)sender {//获取维度跨度并缩小一倍CGFloatlatitudeDelta =self.mapView.region.span.latitudeDelta *0.5;//获取经度跨度并缩小一倍CGFloatlongitudeDelta =self.mapView.region.span.longitudeDelta *0.5;//经纬度跨度MKCoordinateSpanspan =MKCoordinateSpanMake(latitudeDelta, longitudeDelta);//设置当前区域MKCoordinateRegionregion =MKCoordinateRegionMake(self.mapView.centerCoordinate, span);        [self.mapView setRegion:region animated:YES];}

向mapView上添加大头针

只要我们的NSObject实现MKAnnotation协议,就可以作为一个大头针供我们使用,通常我们在我们的类中要重写协议中coordinate(标记位置)、title(标题)、subtitle(子标题)三个属性,然后在程序中创建大头针对象并调用addAnnotation:方法添加大头针即可

ZKAnnotation.h

#import#import//遵循协议@interfaceZKAnnotation:NSObject//经纬度@property(nonatomic)CLLocationCoordinate2Dcoordinate;//父标题@property(nonatomic,copy)NSString*title;//子标题@property(nonatomic,copy)NSString*subtitle;@end

ViewController.h

#import"ViewController.h"#import#import"ZKAnnotation.h"@interfaceViewController()//mapView视图@property(weak,nonatomic)IBOutletMKMapView*mapView;@end@implementationViewController- (void)viewDidLoad {    [superviewDidLoad];    ZKAnnotation *annotation=[[ZKAnnotation alloc]init];    annotation.coordinate=CLLocationCoordinate2DMake(39.9,116);    annotation.title=@"我是父标题";    annotation.subtitle=@"我是子标题";self.mapView.delegate=self;//添加大头针到北京[self.mapView addAnnotation:annotation];}//当点击屏幕的时候调用- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent*)event{//获取用户点击的位置CGPointpoint=[[touches anyObject]locationInView:self.mapView];//将具体的位置转换为经纬度CLLocationCoordinate2Dcoordinate=[self.mapView convertPoint:point toCoordinateFromView:self.mapView];//添加大头针ZKAnnotation *annotation=[[ZKAnnotation alloc]init];    annotation.coordinate=coordinate;//反地理编码CLGeocoder*geocoder=[[CLGeocoderalloc]init];CLLocation*location=[[CLLocationalloc]initWithLatitude:coordinate.latitude longitude:coordinate.longitude];    [geocoder reverseGeocodeLocation:location completionHandler:^(NSArray * _Nullable placemarks,NSError* _Nullable error) {if(error==nil&& placemarks.count==0) {NSLog(@"错误信息:%@",error);return;        }//获取地标信息CLPlacemark*placemark=[placemarks firstObject];//获取父标题名称annotation.title=placemark.locality;//获取子标题名称annotation.subtitle=placemark.name;//添加大头针到地图[self.mapView addAnnotation:annotation];    }];    }

效果如下

mapView.gif

动态添加大头针到地图

ZKAnnotation.h

#import#import@interfaceZKAnnotation:NSObject//经纬度@property(nonatomic)CLLocationCoordinate2Dcoordinate;//标题@property(nonatomic,copy)NSString*title;//子标题@property(nonatomic,copy)NSString*subtitle;@end

ViewController.m

#import"ViewController.h"#import#import"ZKAnnotation.h"@interfaceViewController()//创建管理者@property(nonatomic,strong)CLLocationManager*locationManager;//mapView@property(weak,nonatomic)IBOutletMKMapView*mapView;@end@implementationViewController- (void)viewDidLoad {    [superviewDidLoad];// 1.创建大头针模型ZKAnnotation *annotation = [[ZKAnnotation alloc] init];    annotation.coordinate =CLLocationCoordinate2DMake(39.9,116);    annotation.title =@"北京";    annotation.subtitle =@"默认显示的为首都北京";//添加第一个大头针模型[self.mapView addAnnotation:annotation];//设置代理self.mapView.delegate =self;//请求授权self.locationManager = [[CLLocationManageralloc] init];    [self.locationManager requestWhenInUseAuthorization];//设置用户跟踪模式//self.mapView.userTrackingMode = MKUserTrackingModeFollow;}//点击屏幕的时候调用- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent*)event{//获取用户点击的位置CGPointpoint=[[touches anyObject]locationInView:self.mapView];//将具体的位置转换为经纬度CLLocationCoordinate2Dcoordinate=[self.mapView convertPoint:point toCoordinateFromView:self.mapView];//添加大头针ZKAnnotation *annotation=[[ZKAnnotation alloc]init];    annotation.coordinate=coordinate;//反地理编码CLGeocoder*geocoder=[[CLGeocoderalloc]init];CLLocation*location=[[CLLocationalloc]initWithLatitude:coordinate.latitude longitude:coordinate.longitude];    [geocoder reverseGeocodeLocation:location completionHandler:^(NSArray * _Nullable placemarks,NSError* _Nullable error) {if(error==nil&& placemarks.count==0) {NSLog(@"错误信息:%@",error);return;        }//获取地标信息CLPlacemark*placemark=[placemarks firstObject];//获取父标题名称annotation.title=placemark.locality;//获取子标题名称annotation.subtitle=placemark.name;//添加大头针到地图[self.mapView addAnnotation:annotation];    }];}//创建大头针时调用- (MKAnnotationView*)mapView:(MKMapView*)mapView viewForAnnotation:(id)annotation{//如果返回空,代表大头针样式交由系统去管理if([annotation isKindOfClass:[MKUserLocationclass]]) {returnnil;    }staticNSString*ID =@"annotation";// MKAnnotationView 默认没有界面  可以显示图片// MKPinAnnotationView有界面      默认不能显示图片MKPinAnnotationView*annotationView = (MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:ID];if(annotationView ==nil) {        annotationView = [[MKPinAnnotationViewalloc] initWithAnnotation:annotation reuseIdentifier:ID];//设置大头针颜色annotationView.pinTintColor = [UIColorredColor];//设置为动画掉落的效果annotationView.animatesDrop =YES;//显示详情annotationView.canShowCallout =YES;    }returnannotationView;}@end

效果如下

动态添加大头针.gif

作者:J_mailbox

链接:https://www.jianshu.com/p/6fcb3cd01e3e

來源:简书

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容