【iOS开发-109】CoreLocation框架的两个主要类CLLocationManager和CLGeoCoder介绍

CoreLocation框架主要由两个常用的类,一个是CLLocationManager,一个是CLGeoCoder。


(1)CoreLocation的使用,先导入CoreLocation框架。


(2)一般是利用位置管理器来操作,即CLLocationManager

——开启,就是startUpdatingLocation;关闭,就是stopUpdatingLocation

——可以先判断位置服务是否开启locationServicesEnabled,如果没开启,直接返回空,不操作。

——iOS8的推送信息,需要获得用户允许,注册以下推送通知

——位置类CLLocation有很多属性,包括方向course,还有坐标coordinate,coordinate有经纬度属性latitude和longitude。

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

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

@implementation ViewController
-(CLLocationManager *)locMgr{
    //判断,定位服务是否开启,如果没开启,直接返回nil,不执行下面的操作
    if (![CLLocationManager locationServicesEnabled]) return nil;
    
    if (!_locMgr) {
        _locMgr=[[CLLocationManager alloc]init];
    }
    return _locMgr;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    if ([[UIDevice currentDevice].systemVersion doubleValue]>=8.0) {
                
    }
    //设置代理
    self.locMgr.delegate=self;
    [self.locMgr startUpdatingLocation];
}

-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
    CLLocation *loc=[locations firstObject];
    NSLog(@"%f %f",loc.coordinate.latitude,loc.coordinate.longitude);
    //如果只需要调用1次,则立即关闭,因为默认每隔一分钟调用一次这个方法,耗电
    [manager stopUpdatingLocation];
}

@end

——推送通知允许的个性化设置

技术分享

技术分享

(3)计算两个位置之间的直线距离

    CLLocation *loc1=[[CLLocation alloc]initWithLatitude:44 longitude:120];
    CLLocation *loc2=[[CLLocation alloc]initWithLatitude:45 longitude:120];
    CLLocationDistance distance=[loc1 distanceFromLocation:loc2];
    NSLog(@"%f",distance);

结果是:111122.007528

表示位置的属性还有海拔等等,用如下方法可以一窥:

CLLocation *loc2=[[CLLocation alloc]initWithCoordinate:(CLLocationCoordinate2D) altitude:(CLLocationDistance) horizontalAccuracy:(CLLocationAccuracy) verticalAccuracy:(CLLocationAccuracy) timestamp:(NSDate *)];

当然,我们可以自己make一个坐标等等。


(4)还有一些针对位置管理器的属性介绍

    //每隔多远距离更新一次
    self.locMgr.distanceFilter=distance;
    //精度设置
    self.locMgr.desiredAccuracy=kCLLocationAccuracyBestForNavigation;

(5)在iOS7中,需要用户授权,但是不需要开发者额外设置,会自动有弹窗出来。但是在iOS8中,尽管注册了推送消息的通知,但是仍然无效,需要有特殊设置:

——首先,最核心的就是调用方法requestWhenInUseAuthorization或者requestAlwaysAuthorization,两者区别在于,一个是告诉用户只在用户使用这个app时访问位置信息,而后者是不管你正在用或者放在后台,都使用位置信息。而且区别在于,如果选择后者的话,那么弹框出来的信息是带有自定义的信息的(即上面所说的个性化设置说明信息)。

- (void)viewDidLoad {
    [super viewDidLoad];
    if ([[UIDevice currentDevice].systemVersion doubleValue]>=8.0) {
        [self.locMgr requestWhenInUseAuthorization];
    }
    [self.locMgr startUpdatingLocation];
}

——当然,仅仅调用以上语句还是不够。还需要在info.plist中添加对应的属性,当然,两个都添加了也没事。

技术分享


(6)如果不需要关心用户的地点信息,只需要简单地经纬度和地址之间的转换,那么就是地理编码和发地理编码。

地理编码:把地点名称,转换成经纬度以及更详细的地址。反地理编码,就是输入经纬度,获取详细地址。主要代码如下:

- (IBAction)geoCode:(id)sender {
    if (self.addressField.text.length==0) return;
    [self.geocoder geocodeAddressString:self.addressField.text completionHandler:^(NSArray *placemarks, NSError *error) {
        if (error) {
            self.detailAddressLabel.text=@"找不到你输入的详细地址";
        }else{
            CLPlacemark *pm=[placemarks firstObject];
            self.longitudeLabel.text=[NSString stringWithFormat:@"%.1f",pm.location.coordinate.longitude];
            self.latitudeLabel.text=[NSString stringWithFormat:@"%.1f",pm.location.coordinate.latitude];
            self.detailAddressLabel.text=pm.name;
        }
    }];
}
- (IBAction)reverseGeoCode:(id)sender {
    if (self.reverseLongitudeField.text.length==0 || self.reverseLatitudeField.text.length==0) return;
    CLLocation *loc=[[CLLocation alloc]initWithLatitude:[self.reverseLatitudeField.text doubleValue] longitude:[self.reverseLongitudeField.text doubleValue]];
    [self.geocoder reverseGeocodeLocation:loc completionHandler:^(NSArray *placemarks, NSError *error) {
        if (error) {
            self.reverseDetailAddressLabel.text=@"这是什么经纬度?";
        }else{
            CLPlacemark *pm=[placemarks firstObject];
            self.reverseDetailAddressLabel.text=pm.name;
        }
    }];
}

技术分享


(7)补充CLLocationManager的另一个知识,范围的监控。比如360儿童手表的进入某个区域和离开某个区域就警报的功能。

——得遵守协议<CLLocationManagerDelegate>

——然后,创建一个区域,下面的第一个方法已经报销了,现在用第二个方法,即CLRegion用CLCircularRegion来创建这个不太容易想到。

CLRegion *region=[[CLRegion alloc]initCircularRegionWithCenter:(CLLocationCoordinate2D) radius:(CLLocationDistance) identifier:@"china"];
CLRegion *region=[[CLCircularRegion alloc]initWithCenter:(CLLocationCoordinate2D) radius:(CLLocationDistance) identifier:(NSString *)];
——然后,发起监控

[self.locMgr startMonitoringForRegion:region];

——当然,有代理方法,即进入这个范围或者离开的时候,做什么事情,就在代理方法里做:

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

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

——当然,关闭监控区域的方法是:

[self.locMgr stopMonitoringForRegion:region];

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。