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];