oc之定位CllocationManage类
#import <CoreLocation/CoreLocation.h>
class <CLLocationManagerDelegate>
{
CLLocationManager * locationManager;
NSString * currentCity; //当前城市
}
#pragma mark -定位
- (void)locate {
//判断定位功能是否打开
if ([CLLocationManager locationServicesEnabled]) {
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
// [locationManager requestAlwaysAuthorization];
currentCity = [[NSString alloc] init];
[locationManager startUpdatingLocation];
}
}
#pragma mark CoreLocation delegate
//定位失败则执行此代理方法
//定位失败弹出提示框,点击"打开定位"按钮,会打开系统的设置,提示打开定位服务
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
UIAlertController * alertVC = [UIAlertController alertControllerWithTitle:@"允许\"定位\"提示" message:@"请在设置中打开定位" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction * ok = [UIAlertAction actionWithTitle:@"打开定位" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
//打开定位设置
NSURL *settingsURL = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
[[UIApplication sharedApplication] openURL:settingsURL];
}];
UIAlertAction * cancel = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
}];
[alertVC addAction:cancel];
[alertVC addAction:ok];
[self presentViewController:alertVC animated:YES completion:nil];
}
//定位成功
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
[locationManager stopUpdatingLocation];
CLLocation *currentLocation = [locations lastObject];
CLGeocoder * geoCoder = [[CLGeocoder alloc] init];
//反编码
[geoCoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
if (placemarks.count > 0) {
CLPlacemark *placeMark = placemarks[0];
currentCity = placeMark.locality;
if (!currentCity) {
currentCity = nil;
}
NSLog(@"%@",currentCity); //这就是当前的城市
NSLog(@"%@",placeMark.name);//具体地址: xx市xx区xx街道
}
else if (error == nil && placemarks.count == 0) {
NSLog(@"No location and error return");
currentCity = nil;
}
else if (error) {
NSLog(@"location error: %@ ",error);
currentCity = nil;
}
}];
}
IOS 之 Core Loaction 定位服务与地图
https://blog.csdn.net/samrtian/article/details/14087233
使用CLLoactionManager类之前得加入 CoreLocation框架
然后加入头文件
#import<CoreLocation/CoreLocation.h>
#import<CoreLocation/CLLocationManagerDelegate>
接着定义变量
CLLocationManager* location;
_location = [[CLLocationManageralloc]init];
_location.delegate =self;
_location.desiredAccuracy =kCLLocationAccuracyBest; //设置精确度到M 精确越大越耗电
_location.distanceFilter = 1000.0f; //多少距离侦测一次
[_locationstartUpdatingLocation]; //开始侦测
[_location stopUpdatingLocation]; //停止侦测
//委托方法
//更新方法
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
CLLocation* lo = [locations lastObject];
_pointX.text = [NSString stringWithFormat:@"%g", lo.coordinate.longitude];
_pointY.text = [NSString stringWithFormat:@"%g", lo.coordinate.latitude];
CLGeocoder *geocoder = [CLGeocoder new];
[geocoder reverseGeocodeLocation:lo completionHandler:^(NSArray *placemarks, NSError *error) {
if ( [placemarks count] > 0 ) {
CLPlacemark* placemark = placemarks[0];
NSDictionary *dictAddress = placemark.addressDictionary;
NSString *strAddress = [dictAddress objectForKey:(NSString*)kABPersonAddressStateKey];
self.address.text = strAddress;
NSLog(@"地址: %@", strAddress);
}
}];
}
//失败时调用的方法
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
CLLocation* lo; 属性
lo.coordinate.longitude //精度
lo.coordinate.latitude //纬度
lo.horizontalAccuracy //中心圆半径.相当于地图上你看到的自己所在的一个圆圈 值越大位置越不确定 为负时就不能依赖坐标值了.
lo.altitude //海平面上下多少米
lo.verticalAccuracy //海拨, 为负不确定海拨
ClLocationDistance distance = [lo distanceFromLocation: CLLocation* lo]; //计算两个之间的距离
//地理信息反编码,就是把看不懂的坐标数字转换为地点的相关描述,包括国家,市,街道,很准确
//使用这个类取地址信息的时候还需要引入
#import <AddressBook/AddressBook.h>
CLGeocoder *geocoder = [CLGeocodernew]; //反编码类
CLPlacemark* placemark = placemarks[0]; //封装着地点相关信息
placemark.addressDictionary //地址信息的字典,包含一些键值对,在地址簿框架中
placemark.ISOcountryCode //ISO国家代号
placemark.postalCode //邮政编码
placemark.administrativeArea //行政区域信息
placemark.subAdministrativeArea //行政区域附加信息
placemark.locality //指定城市信息
placemark.subLocality //指定城市信息附加信息
placemark.thoroughfare //指定街道级别信息
placemark.subThoroughfare //指定街道级别的附加信息
//通过地址信息查询
geocodeAddressString:completionHandler:
//这个网址可以是地图上的一些资料也可以生成GPX文件
http://mygeoposition.com
//关于地图相关的IOS6自带的地图
核心视图类是MKMapView,委托协议是MKMapViewDelegate 使用时需要导入MapKit框架.
#import <MapKit/MapKit.h>
MKMapView *mapView;
mapView.mapType
有以下几个类型
MKMapTypeStandard 标准地图
MKMapTypeStatellite 卫星地图
MKMapTypeHybrid 混合地图
mapView.showUserLocation 允许跟踪显示用户位置信息
setUserTrackingMode:MKUserTrackingModeFloow:animated: 设置跟踪模式 还得实现委托方法
MKUserTrackingModeNone 没有用户跟踪模式
MKUserTrackingModeFollow 可以跟踪用户的位置变化
MKUserTrackingModeFollowWithHeading 可以跟踪用户的位置和方向变化
//设置跟踪用户
-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
_mapView.centerCoordinate = userLocation.location.coordinate;
}
//添加地图标注
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
CLLocation* lo = [locations lastObject];
_pointX.text = [NSString stringWithFormat:@"%g", lo.coordinate.longitude];
_pointY.text = [NSString stringWithFormat:@"%g", lo.coordinate.latitude];
CLGeocoder *geocoder = [CLGeocoder new];
[geocoder reverseGeocodeLocation:lo completionHandler:^(NSArray *placemarks, NSError *error) {
if ( [placemarks count] > 0 ) {
[_mapView removeAnnotations:_mapView.annotations];
CLPlacemark* placemark = placemarks[0];
//调整地图位置和缩放比例
MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(placemark.location.coordinate, 10000, 10000);
[_mapView setRegion:viewRegion animated:YES];
LocationInfo *locationInfo = [LocationInfo new];
locationInfo.stree = placemark.thoroughfare;
locationInfo.coordinate = placemark.location.coordinate;
//这个动作会触发下边委托方法
[_mapView addAnnotation:locationInfo];
}
}];
}
//被上边的add动作调用最后一个参数就是上边的locationInfo,这个必须自己定义而且还得实现MKAnnotation协议
//地图类的委托方法. 用于显示地图上的标注
-(MKAnnotationView *)mapView:(MKMapView *)themapView viewForAnnotation:(id<MKAnnotation>)annotation
{
MKPinAnnotationView *annotationView = (MKPinAnnotationView *)[_mapView dequeueReusableAnnotationViewWithIdentifier:@"PIN_ANNOTATION"];
if ( annotationView == nil ) {
annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"PIN_ANNOTATION"];
}
annotationView.pinColor = MKPinAnnotationColorPurple; //大头针的颜色
annotationView.animatesDrop = YES; //设置标注视图时是否以动画效果
annotationView.canShowCallout = YES; //显示气泡提示信息
return annotationView;
}
//使用程序外的苹果地图
需要使用MKPlacemark和MKMapItem这两个类
- (IBAction)query:(id)sender {
CLLocationCoordinate2D ll2d = _sPoint.coordinate; //_sPoint是CLLoation类
NSDictionary *address = _place.addressDictionary; //_place是 CLPlaceMark类
MKPlacemark *place1 = [[MKPlacemark alloc] initWithCoordinate:ll2d addressDictionary:address];
MKMapItem *mapItem = [[MKMapItem alloc] initWithPlacemark:place1];
[mapItem openInMapsWithLaunchOptions:nil];
}
//调用谷歌WEB地图
- (IBAction)query:(id)sender {
NSString *urlString = [NSString stringWithFormat:@"http://maps.google.com/maps?q=%f,%f", _sPoint.coordinate.latitude, _sPoint.coordinate.longitude];
NSURL *url = [NSURL URLWithString:urlString];
[[UIApplication sharedApplication] openURL:url];
}
来源:CSDN
原文:https://blog.csdn.net/samrtian/article/details/14087233
版权声明:本文为博主原创文章,转载请附上博文链接!
地图之CLLocationManager的使用
https://www.jianshu.com/p/ef6994767cbb
1.iOS8以前使用CLLocationManager
1.导入头文件 <CoreLocation/CoreLocation.h>
2.创建位置管理者 CLLocationManager , 并添加到属性。
3.设置代理、遵守协议、实现代理方法,在代理方法中获取位置信息
4.调用开始更新位置方法
5.设置 每隔多远定位一次 和 精确度,精确度越高越耗电,定位时间越长
// 1.设置位置管理者属性
@property (nonatomic, strong) CLLocationManager *lcManager;
// 2.判断是否打开了位置服务
if ([CLLocationManager locationServicesEnabled]) {
// 创建位置管理者对象
self.lcManager = [[CLLocationManager alloc] init];
self.lcManager.delegate = self; // 设置代理
// 设置定位距离过滤参数 (当本次定位和上次定位之间的距离大于或等于这个值时,调用代理方法)
self.lcManager.distanceFilter = 100;
self.lcManager.desiredAccuracy = kCLLocationAccuracyBest; // 设置定位精度(精度越高越耗电)
[self.lcManager startUpdatingLocation]; // 开始更新位置
}
/** 获取到新的位置信息时调用*/
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
NSLog(@"定位到了");
}
/** 不能获取位置信息时调用*/
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(@"获取定位失败");
}
6.请求授权,iOS6之后,苹果开始加强保护用户隐私,在 Info.plist 文件中定义 Key提醒用户,提高用户允许定位的概率。
Info.plist 设置Key
7.如果要后台定位,需要打开后台模式
勾选后台模式
2.iOS8.0之后使用CLLocationManager
1.iOS8之后,苹果又进一步加强了隐私保护,不会主动填出对话框,让用户选择
2.需要实现两个方法(实现其一即可),并且 Info.plist 中设置对应的 key ,才会弹框
1.requestWhenInUseAuthorization
1.当程序当前的授权状态为未决定时,在前台时请求定位服务许可时使用。需要先在 Info.plist 文件中设置一个Key:NSLocationWhenInUseUsageDescription, 如果不设置key,系统会忽略定位请求。
Info.plist 设置对应的Key
2.当用户授权 when-in-use时,程序在前台时可以启动大部分定位服务。如果想要后台定位,需要开启后台定位模式,但在状态栏会出现蓝条提示用户程序正在进行定位。
[_lcManager requestWhenInUseAuthorization];
请求定位的弹框
后台模式下的 blue bar
2.requestAlwaysAuthorization
1.请求前后台定位服务授权,当授权状态为未决定时请求用户授权。前提是在 Info.plist 文件中包含key NSLocationAlwaysUsageDescription
Info.plist中 设置对应的Key
请求定位的弹框
3.注意
1.iOS8之后,如果想要定位,必须调用 requestWhenInUseAuthorization 或 requestAlwaysAuthorization方法。
2.如果两个请求授权的方法都执行了,会出现以下情况
1.when-in-use写在前面,第一次打开程序时请求授权,如果勾选了后台模式,进入后台会出现蓝条提示正在定位。当程序退出,第二次打开程序时 Always 会再次请求授权。之后进入后台就不会出现蓝条了(前后台都能定位)。
2.Always写在前面, when-in-use写在后面,只会在第一次打开程序时请求授权,因为 Always得到的授权大于when-in-use的到的授权
4.判断是否开启了定位服务
在启动更新位置之前要先判断是否开启了定位服务
if ([CLLocationManager locationServicesEnabled]) { // 判断是否打开了位置服务
[self.lcManager startUpdatingLocation]; // 开始更新位置
}
5.适配版本号的方法
when-in-use和 Always 都是iOS8之后出现的方法,如果不进行版本适配,运行在iOS7上就会crash,此时需要做版本号判断
1.判断版本号
if ([[UIDevice currentDevice].systemVersion floatValue] >=8.0 ) {
[_lcManager requestAlwaysAuthorization];
}
2.适配版本的另一种方法
if ([_lcManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
[_lcManager requestWhenInUseAuthorization];
}
6.监听定位服务状态的改变
实现代理方法,判断定位服务的状态
/** 定位服务状态改变时调用*/
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
switch (status) {
case kCLAuthorizationStatusNotDetermined:
{
NSLog(@"用户还未决定授权");
break;
}
case kCLAuthorizationStatusRestricted:
{
NSLog(@"访问受限");
break;
}
case kCLAuthorizationStatusDenied:
{
// 类方法,判断是否开启定位服务
if ([CLLocationManager locationServicesEnabled]) {
NSLog(@"定位服务开启,被拒绝");
} else {
NSLog(@"定位服务关闭,不可用");
}
break;
}
case kCLAuthorizationStatusAuthorizedAlways:
{
NSLog(@"获得前后台授权");
break;
}
case kCLAuthorizationStatusAuthorizedWhenInUse:
{
NSLog(@"获得前台授权");
break;
}
default:
break;
}
}
7.代理方法返回的 locations 信息
当位置管理器,获取到位置后,调用 locationManager:didUpdateLocations:方法,返回的类型为 CLLocation 的位置信息数组,以下为数组包含的属性
1.coordinate : 当前位置的坐标
latitude : 纬度
longitude : 经度
2.altitude : 海拔,高度
3.horizontalAccuracy : 纬度和经度的精度
4.verticalAccuracy : 垂直精度(获取不到海拔时为负数)
5.course : 行进方向(真北)
6.speed : 以米/秒为单位的速度
7.description : 位置描述信息
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
CLLocation *location = [locations firstObject];
NSLog(@"%@", location);
}
3.iOS9.0之后使用CLLocationManager
1.iOS9.0之后有一种新的请求定位的方法 requestLocation
2.作用:按照定位精确度从低到高进行排序,逐个进行定位。如果获取到的位置不是精确度最高的那个,也会在定位超时后,通过代理告诉外界。
3.注意:
1.必须实现 ocationManager:didUpdateLocations: 和 locationManager:didFailWithError 方法,但是只调用一次
2.不能与startUpdatingLocation同时使用
if ([CLLocationManager locationServicesEnabled]) { // 判断是否打开了位置服务
[self.lcManager requestLocation];
}
4.实现 requestWhenInUseAuthorization 或 requestAlwaysAuthorization 方法,并设置对应的 key
if ([[UIDevice currentDevice].systemVersion floatValue] >=8.0 ) {
// iOS0.0:如果当前的授权状态是使用是授权,那么App退到后台后,将不能获取用户位置,即使勾选后台模式:location
[_lcManager requestWhenInUseAuthorization];
}
5.必须勾选后台模式,并设置 allowsBackgroundLocationUpdates 属性为YES(默认是NO)
1.当定位完成时,设置为NO,并且不再定位跟踪
2.使用 -responsdToSelector: 判断
// iOS9.0+ 要想继续获取位置,需要使用以下属性进行设置(注意勾选后台模式:location)但会出现蓝条
if ([_lcManager respondsToSelector:@selector(allowsBackgroundLocationUpdates)]) {
_lcManager.allowsBackgroundLocationUpdates = YES;
}
链接:https://www.jianshu.com/p/ef6994767cbb
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。