iOS开发 --- 定位功能(系统框架CoreLocation)

最近在做定位功能,只需要获取当前位置信息,包括经纬度、位置等,不需要持续获取。

对CoreLocation的封装。将定位相关的代码从 Controller 中分离,封装到 NSObject 对象中。采用 代理方法 降低代码的分散度,方便调用亦易于获取位置信息。

1,初始化

//初始化
- (instancetype)init {
    if (self = [super init]) {
       //创建CLLocationManager对象
        _locationManager = [[CLLocationManager alloc] init];

        _locationManager.desiredAccuracy = kCLLocationAccuracyBest;
        _locationManager.distanceFilter = 10.0;
        _locationManager.delegate = self;
        //请求用户授权
        if ([_locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
            //当用户使用的时候授权
            [_locationManager requestWhenInUseAuthorization];
        }
    }
    return self;
}

2,代理方法 

#pragma mark - CLLocationManagerDelegate
/**
 location.coordinate:坐标,包含经纬度
 location.altitude:设备海拔高度单位是米
 location.course:设置前进方向
 location.horizontalAccuracy:水平精准度
 location.verticalAccuracy:垂直精准度
 location.timestamp:定位信息返回的时间
 location.speed:设备移动速度单位是米/秒,适用于行车速度而不太适用于不行
 */

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations{
    //结束,防止重发定位
    //如果只需要获取一次,可以获取到位置之后就停止
    [self.locationManager stopUpdatingLocation];
    if (self.locationTimes != 0) return;
   //拿到最新的location
    CLLocation *currentLocation = [locations lastObject];
    //反编码
    CLGeocoder * geoCoder = [[CLGeocoder alloc] init];
    [geoCoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
        if (placemarks.count > 0) {
            //将字典转为模型
            NSDictionary *dic = [self getInfoWithPlacemark:placemarks[0]];
            LocationModel *model = [[LocationModel alloc]init];
            [model setValuesForKeysWithDictionary:dic];
            
            //首次判断代理是否存在,并在代理能够响应代理方法时才执行代理方法
            if (self.ldelegate && [self.ldelegate respondsToSelector:@selector(doSomethingAfterGetCityInformation:)]) {
                [self.ldelegate doSomethingAfterGetCityInformation:model];
            }
        }
        else if (error == nil && placemarks.count == 0) {
            NSLog(@"No location and error return");
        }
        else if (error) {
            NSLog(@"location error: %@ ",error);
        }
    }];
    
    self.locationTimes ++;
}
/**
授权状态
*/
- (void)locationManager:(CLLocationManager*)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status{
    if(status ==kCLAuthorizationStatusNotDetermined) {
        NSLog(@"等待用户授权");
    }else if(status ==kCLAuthorizationStatusAuthorizedAlways||
             status ==kCLAuthorizationStatusAuthorizedWhenInUse){
        NSLog(@"授权成功");
        //开始定位
        [self.locationManager startUpdatingLocation];
    }else{
        NSLog(@"授权失败");
    }
}
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
    NSLog(@"E:%@",error);
    if ([error code] == kCLErrorDenied) {
        NSLog(@"错误:拒绝定位");
    }else if ([error code] == kCLErrorLocationUnknown) {
        NSLog(@"错误:无法获取定位");
    }else {
        NSLog(@"%@",error.localizedDescription);
    }
}

3,整理位置信息 

#pragma mark - 整理位置信息
- (NSDictionary *)getInfoWithPlacemark:(CLPlacemark *)placemark {
    
    // 经纬度
    CLLocationCoordinate2D coordinate = placemark.location.coordinate;
    NSString *longitude = [NSString stringWithFormat:@"%f",coordinate.longitude];
    NSString *latitude = [NSString stringWithFormat:@"%f",coordinate.latitude];
    
    // 省/市/县(区)/街道/详细地址
    NSString *province = placemark.administrativeArea;
    NSString *locality = placemark.locality;
    province = province ? province : placemark.locality;//若省不存在则为直辖市
    NSString *subCity = placemark.subLocality;
    NSString *street = placemark.addressDictionary[@"Street"];
//    NSString *name = placemark.name;
    NSString *address;
    if ([province isEqualToString:locality]) {
        address = [NSString stringWithFormat:@"%@%@%@",locality,subCity,street];
    }else {
        address = [NSString stringWithFormat:@"%@%@%@%@",province,locality,subCity,street];
    }
    NSDictionary *dic = @{@"longitude"  :longitude,
                          @"latitude"   :latitude,
                          @"province"   :province,
                          @"locality"   :locality,
                          @"subLocality":subCity,
                          @"street"     :street,
                          @"address"    :address};
    return dic;
}

4,使用 

#import "ACCoreLocationViewController.h"
#import <CoreLocation/CoreLocation.h>
@interface ACCoreLocationViewController ()<CLLocationManagerDelegate>
@property (nonatomic,strong) CLLocationManager *locationManager;
@end

@implementation ACCoreLocationViewController

- (void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    [self.locationObject start];
}

- (void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
    [self.locationObject end];
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
           
    self.locationObject = [[ACCoreLocationObject alloc]init];      
    _locationObject.ldelegate = self;
}

/**
代理方法
*/
-(void)doSomethingAfterGetCityInformation:(LocationModel *)model{
    NSLog(@"城市%@",model.locality);    
}

注意:

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations;

这个方法每隔一段时间就会调用一次,所以如果只需要定位一次的话,要做相应的处理。

  • 只获取一次定位
[self.locationManager requestLocation];
  • 一直持续获取定位
[self.locationManager startUpdatingLocation];

参考文章

CoreLocation定位封装

IOS 定位 CoreLocation的封装

iOS:CoreLocation实现定位当前城市

IOS位置和地图 CoreLocation框架

CoreLocation(地理定位)的基本使用

iOS开发-用户定位获取-CoreLocation的实际应用

猜你喜欢

转载自blog.csdn.net/jiaxin_1105/article/details/109721832
今日推荐