获取本机当前经纬度坐标位置和通过经纬度坐标测算距离(iOS)

681人浏览 / 0人评论 / 添加收藏

平时我们再写程序的时候经常会需要访问当前设备的位置信息和计算当前位置距某点的距离,下面我来为大家浅谈一下使用OC自带的库来获取当前坐标和其的距离计算。

一、获取当前经纬度坐标
步骤1:添加关键字
首先要Info里添加两个键值对,向用户请求位置服务时会显示在这里设置的值的内容。

<key>NSLocationWhenInUseUsageDescription</key>
<value>使用程序的时候获取本机位置</value>

<key>NSLocationAlwaysUsageDescription</key>
<value>总是获取本机位置</value>
 

步骤2:导入头文件
#import <CoreLocation/CoreLocation.h>
这个是OC自带的一个库,不需要再导入其他的第三方库了。

步骤3:遵循相关协议
<CLLocationManagerDelegate>
因为我们需要使用到其相关的协议函数来实现,所以我们需要遵循其相关协议。

步骤4:设置属性,开始定位
我们在开始定位之前需要设置一个定位管理者的属性,并且它只能设置为属性,当你没设置属性的时候,软件开启时提示定位的提示出现一瞬间就消失了。

//设置一个定位管理者
@property (nonatomic, strong) CLLocationManager *locationManager;
如果你只想获取当前经纬度坐标的话定义一个这个就足够了,若是你还想获取当前位置的更多信息那么你还需要再设置一个下面这个属性:

//存储推算出当前位置的地理信息
@property (nonatomic, strong) CLGeocoder *geoCoder;

这个属性用于获取通过当前位置坐标推算出来的更多的位置信息,比如市、区、名字等等。
定义完属性之后,下面开始定位:

//开始定位
- (void)startLocation {
   //初始化定位管理者
   self.locationManager = [[CLLocationManager alloc] init];
   //判断设备是否能够进行定位
   if ([CLLocationManager locationServicesEnabled]) {
       self.locationManager.delegate = self;
       //精确度获取到米
       self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
       //设置过滤器为无
       self.locationManager.distanceFilter = kCLDistanceFilterNone;
       // 取得定位权限,有两个方法,取决于你的定位使用情况
       //一个是requestAlwaysAuthorization,一个是requestWhenInUseAuthorization
       [self.locationManager requestWhenInUseAuthorization];
       //开始获取定位
       [self.locationManager startUpdatingLocation];
       //地理信息
       self.geoCoder = [[CLGeocoder alloc] init];
   } else {
       NSLog(@"error");
   }
}
CLLocationManager其相关的属性:
desiredAccuracy位置的精度属性,取值有如下几种:

kCLLocationAccuracyBest 精确度最佳
kCLLocationAccuracynearestTenMeters 精确度10m以内
kCLLocationAccuracyHundredMeters 精确度100m以内
kCLLocationAccuracyKilometer 精确度1000m以内
kCLLocationAccuracyThreeKilometers 精确度3000m以内
delegate:响应CLLocationManagerdelegate的对象
distanceFilter:横向移动多少距离后更新位置信息

步骤5:在对应的代理方法中获取到我们需要的位置信息
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations在此代理方法中我们可以获取到当前位置的经纬度。
注意: locations是一个数组类型,它的最后一个元素就是我们获取的经纬度坐标,其类型为CLLocation,我们如果想将其设为属性其修饰符一定要是retain。
下面我定义了一个属性来存储获取到的位置信息:

//获取自身的经纬度坐标
@property (nonatomic, retain) CLLocation *myLocation;

//设置获取位置信息的代理方法
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
   NSLog(@"%lu", (unsigned long)locations.count);
   self.myLocation = locations.lastObject;
   NSLog(@"经度:%f 纬度:%f", _myLocation.coordinate.longitude, _myLocation.coordinate.latitude);
   
   //通过坐标来推算该位置的相关信息
   [self.geoCoder reverseGeocodeLocation:self.myLocation completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
       if (placemarks.count > 0) {
           CLPlacemark *placemark = [placemarks objectAtIndex:0];
           NSLog(@"%@", placemark.name);
           //获取城市
           NSString *city = placemark.locality;
           if (!city) {
               //四大直辖市的城市信息无法通过locality获得,只能通过获取省份的方法来获得(如果city为空,则可知为直辖市)
               city = placemark.administrativeArea;
           }
           // 位置名
           NSLog(@"name, %@", placemark.name);
           // 街道
           NSLog(@"thoroughfare, %@", placemark.thoroughfare);
           // 子街道
           NSLog(@"subThoroughfare, %@", placemark.subThoroughfare);
           // 市
           NSLog(@"locality, %@", placemark.locality);
           // 区
           NSLog(@"subLocality, %@", placemark.subLocality);
           // 国家
           NSLog(@"country, %@", placemark.country);
       } else if (error == nil && [placemarks count] == 0) {
           NSLog(@"No results were returned.");
       } else if (error != nil) {
           NSLog(@"An error occurred = %@", error);
       }
   }];
   //不用的时候关闭更新位置服务,不关闭的话这个 delegate 隔一定的时间间隔就会有回调
   [self.locationManager stopUpdatingLocation];
}
当然不止这些,当获取位置信息出错时,我们会调用下面的协议:

//问题函数
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
   if (error) {
       NSLog(@"error:%ld", (long)error.code);
   }
}
以上就是获取本机当前位置信息的方法了。

二、测算距离
测算两个经纬度坐标之间的距离是非常简单的,并且该库中自带其计算的方法:- (CLLocationDistance)distanceFromLocation:(const CLLocation *)location

CLLocation *before = [[CLLocation alloc] initWithLatitude:39.91667 longitude:116.41667];
   CLLocationDistance meters = [self.myLocation distanceFromLocation:before];
   NSLog(@"相距:%fm", meters);

三、小小的代码测试
ViewController.h

#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>

@interface ViewController : UIViewController<CLLocationManagerDelegate>

@end
 


ViewController.m

#import "ViewController.h"

@interface ViewController ()

//设置一个定位管理者
@property (nonatomic, strong) CLLocationManager *locationManager;
//存储推算出当前位置的地理信息
@property (nonatomic, strong) CLGeocoder *geoCoder;
//获取自身的经纬度坐标
@property (nonatomic, retain) CLLocation *myLocation;

@end

@implementation ViewController

- (void)viewDidLoad {
   [super viewDidLoad];
   // Do any additional setup after loading the view.
   
   self.view.backgroundColor = [UIColor orangeColor];
   
   self.myLocation = [[CLLocation alloc] init];
   
   //执行定位函数
   [self startLocation];
   
}

//开始定位
- (void)startLocation {
   self.locationManager = [[CLLocationManager alloc] init];
   //判断设备是否能够进行定位
   if ([CLLocationManager locationServicesEnabled]) {
       self.locationManager.delegate = self;
       //精确度获取到米
       self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
       //设置过滤器为无
       self.locationManager.distanceFilter = kCLDistanceFilterNone;
       // 取得定位权限,有两个方法,取决于你的定位使用情况
       //一个是requestAlwaysAuthorization,一个是requestWhenInUseAuthorization
       // 这句话ios8以上版本使用。
       [self.locationManager requestWhenInUseAuthorization];
       //开始获取定位
       [self.locationManager startUpdatingLocation];
       //地理信息
       self.geoCoder = [[CLGeocoder alloc] init];
   } else {
       NSLog(@"error");
   }
}

//设置获取位置信息的代理方法
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
   NSLog(@"%lu", (unsigned long)locations.count);
   self.myLocation = locations.lastObject;
   NSLog(@"经度:%f 纬度:%f", _myLocation.coordinate.longitude, _myLocation.coordinate.latitude);
   
   CLLocation *before = [[CLLocation alloc] initWithLatitude:39.91667 longitude:116.41667];
   CLLocationDistance meters = [self.myLocation distanceFromLocation:before];
   NSLog(@"相距:%fm", meters);
   
   [self.geoCoder reverseGeocodeLocation:self.myLocation completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
       if (placemarks.count > 0) {
           CLPlacemark *placemark = [placemarks objectAtIndex:0];
           NSLog(@"%@", placemark.name);
           //获取城市
           NSString *city = placemark.locality;
           if (!city) {
               //四大直辖市的城市信息无法通过locality获得,只能通过获取省份的方法来获得(如果city为空,则可知为直辖市)
               city = placemark.administrativeArea;
           }
           // 位置名
           NSLog(@"name, %@", placemark.name);
           // 街道
           NSLog(@"thoroughfare, %@", placemark.thoroughfare);
           // 子街道
           NSLog(@"subThoroughfare, %@", placemark.subThoroughfare);
           // 市
           NSLog(@"locality, %@", placemark.locality);
           // 区
           NSLog(@"subLocality, %@", placemark.subLocality);
           // 国家
           NSLog(@"country, %@", placemark.country);
       } else if (error == nil && [placemarks count] == 0) {
           NSLog(@"No results were returned.");
       } else if (error != nil) {
           NSLog(@"An error occurred = %@", error);
       }
   }];
   //不用的时候关闭更新位置服务,不关闭的话这个 delegate 隔一定的时间间隔就会有回调
   [self.locationManager stopUpdatingLocation];
}

//问题函数
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
   if (error) {
       NSLog(@"error:%ld", (long)error.code);
   }
}

@end
 

全部评论