IOS CoreLocation框架的使用(用于地理定位)

●  在移动互联网时代,移动app能解决用户的很多生活琐事,比如

 ●  导航:去任意陌生的地方

●  周边:找餐馆、找酒店、找银行、找电影院

●  在上述应用中,都用到了地图定位功能,在iOS开发中,要想加入这大功 能,必须基于2个框架进行开发

●  Map Kit :用于地图展示

●  Core Location :用于地理定位

 

●  2个热门专业术语

●  LBS :Location Based Service

●  SoLoMo :Social Local Mobile(索罗门)

 

 

CoreLocation框架的使用

CoreLocation框架使用前提
导入框架
导入主头文件
#import <CoreLocation/CoreLocation.h>

 

CoreLocation框架使用须知
CoreLocation框架中所有数据类型的前缀都是CL
CoreLocation中使用CLLocationManager对象来做用户定位

 

CLLocationManager

CLLocationManager的常用操作
开始用户定位
- (void)startUpdatingLocation;

 

停止用户定位
- (void) stopUpdatingLocation;

当调用了startUpdatingLocation方法后,就开始不断地定位用户的位 置,中途会频繁地调用代理的下面方法

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

locations参数里面装着CLLocation对象

 

 

CLLocation

CLLocation用来表示某个位置的地理信息,比如经纬度、海拔等等
@property(readonly,nonatomic)CLLocationCoordinate2D
coordinate;

经纬度
@property(readonly,nonatomic)CLLocationDistancealtitude;

海拔
@property(readonly,nonatomic)CLLocationDirectioncourse;

路线,航向(取值范围是0.0°~359.9°,0.0°代表真北方向)
@property(readonly,nonatomic)CLLocationSpeedspeed;

行走速度(单位是m/s)
- (CLLocationDistance)distanceFromLocation:(const CLLocation
*)location

方法可以计算2个位置之间的距离

 

CLLocationManager

@property(assign, nonatomic) CLLocationDistance distanceFilter;

 

每隔多少米定位一次
@property(assign, nonatomic) CLLocationAccuracy
desiredAccuracy;

定位精确度(越精确就越耗电)

 

CLLocationCoordinate2D

CLLocationCoordinate2D是一个用来表示经纬度的结构体,定义如下
typedef struct {

 CLLocationDegrees latitude; // 纬度

CLLocationDegrees longitude; // 经度

}CLLocationCoordinate2D;

 

一般用CLLocationCoordinate2DMake函数来创建CLLocationCoordinate2D

 

用户隐私的保护

 iOS 6开始,苹果在保护用户隐私方面做了很大的加强,以下操作都必须经 过用户批准授权

 ● 要想获得用户的位置
想访问用户的通讯录、日历、相机、相册等等

当想访问用户的隐私信息时,系统会自动弹出一个对话框让用户授权

 

开发者可以在Info.plist中设置NSLocationUsageDescription说明定位的目的 (Privacy - Location Usage Description)

  

 

一旦用户选择了Don’t Allow,意味着你的应用以后就无法使用定位功能
为了严谨起见,最好在使用定位功能之前判断当前应用的定位功能是否可用
CLLocationManager有个类方法可以判断当前应用的定位功能是否可用
+ (BOOL)locationServicesEnabled;

 

 

CLGeocoder

使用CLGeocoder可以完成地理编码反地理编码
地理编码:根据给定的地名,获得具体的位置信息(比如经纬度、地址的全称等) 反地理编码:根据给定的经纬度,获得具体的位置信息

 

地理编码方法

-(void)geocodeAddressString:(NSString*)addressString completionHandler: (CLGeocodeCompletionHandler)completionHandler;

反地理编码方法

-(void)reverseGeocodeLocation:(CLLocation*)location completionHandler: (CLGeocodeCompletionHandler)completionHandler;

 

CLGeocodeCompletionHandler

当地理\反地理编码完成时,就会调用CLGeocodeCompletionHandler
typedef void (^CLGeocodeCompletionHandler)(NSArray*placemarks, NSError *error);

这个block传递2个参数

error :当编码出错时(比如编码不出具体的信息)有值

placemarks :里面装着CLPlacemark对象

 

CLPlacemark

CLPlacemark的字面意思是地标,封装详细的地址位置信息
@property(nonatomic,readonly)CLLocation*location;

地理位置


@property(nonatomic,readonly)CLRegion*region;

区域


@property(nonatomic,readonly)NSDictionary*addressDictionary;

详细的地址信息


@property(nonatomic,readonly)NSString*name;

地址名称

 

@property(nonatomic,readonly)NSString*locality;

城市

 实例:Core Location :用于地理定位

#import "HMViewController.h"
#import <CoreLocation/CoreLocation.h>

@interface HMViewController () <CLLocationManagerDelegate>
@property (nonatomic, strong) CLLocationManager *locMgr;
@end

@implementation HMViewController

- (CLLocationManager *)locMgr
{
    if (!_locMgr) {
        // 1.创建位置管理器(定位用户的位置)
        self.locMgr = [[CLLocationManager alloc] init];
        
        // 2.设置代理
        self.locMgr.delegate = self;
    }
    return _locMgr;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    if ([CLLocationManager locationServicesEnabled]) {
        // 开始定位用户的位置
        [self.locMgr startUpdatingLocation];
        
//        [self.locMgr startMonitoringForRegion:<#(CLRegion *)#>];
        
//        self.locMgr.purpose
        
//        self.locMgr.distanceFilter = kCLDistanceFilterNone;
//        self.locMgr.desiredAccuracy = kcllocationac
    } else { // 不能定位用户的位置
        // 1.告诉用户检查网络状况
        // 2.提醒用户打开定位开关
    }
    
    [self countDistance];
}

- (void)countDistance
{
    CLLocation *loc1 = [[CLLocation alloc] initWithLatitude:40 longitude:116];
    CLLocation *loc2 = [[CLLocation alloc] initWithLatitude:41 longitude:116];
    
    CLLocationDistance distance = [loc1 distanceFromLocation:loc2];
    NSLog(@"(%@)和(%@)的距离:%f", loc1, loc2, distance);
}

#pragma mark - CLLocationManagerDelegate
/**
 *  当定位到用户的位置时,就会调用(调用比较频繁)
 */
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
    // 数组里面存放的是CLLocation对象, 一个CLLocation就代表一个位置
    CLLocation *loc = [locations lastObject];
    
    // 纬度:loc.coordinate.latitude
    // 经度:loc.coordinate.longitude
    NSLog(@"纬度=%f, 经度=%f", loc.coordinate.latitude, loc.coordinate.longitude);
    
    // 停止更新位置(不用定位服务,应当马上停止定位,非常耗电)
    [manager stopUpdatingLocation];
}

//- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
//{
//
//}
//
//- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
//{
//    
//}

@end
View Code

 

实例:地理编码 and 反地理编码

 

#import "HMViewController.h"
#import <CoreLocation/CoreLocation.h>

@interface HMViewController ()
@property (nonatomic, strong) CLGeocoder *geocoder;

#pragma mark - 地理编码
- (IBAction)geocode;
@property (weak, nonatomic) IBOutlet UITextField *addressField;
@property (weak, nonatomic) IBOutlet UILabel *longitudeLabel;
@property (weak, nonatomic) IBOutlet UILabel *latitudeLabel;
@property (weak, nonatomic) IBOutlet UILabel *detailAddressLabel;

#pragma mark - 反地理编码
- (IBAction)reverseGeocode;
@property (weak, nonatomic) IBOutlet UITextField *longtitudeField;
@property (weak, nonatomic) IBOutlet UITextField *latitudeField;
@property (weak, nonatomic) IBOutlet UILabel *reverseDetailAddressLabel;
@end

@implementation HMViewController

- (CLGeocoder *)geocoder
{
    if (!_geocoder) {
        self.geocoder = [[CLGeocoder alloc] init];
    }
    return _geocoder;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    
}

/**
 *  地理编码:地名 -> 经纬度
 */
- (void)geocode
{
    // 1.获得输入的地址
    NSString *address = self.addressField.text;
    if (address.length == 0) return;
    
    // 2.开始编码
    [self.geocoder geocodeAddressString:address completionHandler:^(NSArray *placemarks, NSError *error) {
        if (error || placemarks.count == 0) {
            self.detailAddressLabel.text = @"你输入的地址找不到,可能在火星上";
        } else { // 编码成功(找到了具体的位置信息)
            // 输出查询到的所有地标信息
            for (CLPlacemark *placemark in placemarks) {
                NSLog(@"name=%@ locality=%@ country=%@ postalCode=%@", placemark.name, placemark.locality, placemark.country, placemark.postalCode);
            }
            
            // 显示最前面的地标信息
            CLPlacemark *firstPlacemark = [placemarks firstObject];
            self.detailAddressLabel.text = firstPlacemark.name;
            
            CLLocationDegrees latitude = firstPlacemark.location.coordinate.latitude;
            CLLocationDegrees longitude = firstPlacemark.location.coordinate.longitude;
            self.latitudeLabel.text = [NSString stringWithFormat:@"%.2f", latitude];
            self.longitudeLabel.text = [NSString stringWithFormat:@"%.2f", longitude];
        }
    }];
}

/**
 *  反地理编码:经纬度 -> 地名
 */
- (void)reverseGeocode
{
    NSString *longtitudeText = self.longtitudeField.text;
    NSString *latitudeText = self.latitudeField.text;
    if (longtitudeText.length == 0 || latitudeText.length == 0) return;
    
    CLLocationDegrees latitude = [latitudeText doubleValue];
    CLLocationDegrees longtitude = [longtitudeText doubleValue];
    
    // 开始反向编码
    CLLocation *location = [[CLLocation alloc] initWithLatitude:latitude longitude:longtitude];
    [self.geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
        if (error || placemarks.count == 0) {
            self.reverseDetailAddressLabel.text = @"你输入的经纬度找不到,可能在火星上";
        } else { // 编码成功(找到了具体的位置信息)
            // 输出查询到的所有地标信息
            for (CLPlacemark *placemark in placemarks) {
                NSLog(@"name=%@ locality=%@ country=%@ postalCode=%@", placemark.name, placemark.locality, placemark.country, placemark.postalCode);
            }
            
            // 显示最前面的地标信息
            CLPlacemark *firstPlacemark = [placemarks firstObject];
            self.reverseDetailAddressLabel.text = firstPlacemark.name;
            
            CLLocationDegrees latitude = firstPlacemark.location.coordinate.latitude;
            CLLocationDegrees longitude = firstPlacemark.location.coordinate.longitude;
            self.latitudeField.text = [NSString stringWithFormat:@"%.2f", latitude];
            self.longtitudeField.text = [NSString stringWithFormat:@"%.2f", longitude];
        }
    }];
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self.view endEditing:YES];
}

@end
View Code

 

 

 

 

posted on 2017-05-23 16:26  守望星空  阅读(334)  评论(0编辑  收藏  举报

导航