1.创建CoreLocation的管理者。CoreLocation要强引用
2.实现CLLocationManagerDelegate代理。
3.开始或停止代理
#import <CoreLocation/CoreLocation.h> @interface ViewController () <CLLocationManagerDelegate> @property (nonatomic, strong)CLLocationManager *mrg; @end @implementation ViewController -(CLLocationManager *)mrg { if (_mrg == nil) { //1,创建CoreLocation的管理者 self.mrg = [[CLLocationManager alloc] init]; } return _mrg; } - (void)viewDidLoad { [super viewDidLoad]; //2,成为CoreLocation的代理 self.mrg.delegate = self; //3,开始定位 [self.mrg startUpdatingLocation]; } #pragma mark - CLLocationManagerDelegate -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { NSLog(@"%s",__func__); //打印位置信息 /* location.coordinate; 坐标, 包含经纬度 location.altitude; 设备海拔高度 单位是米 location.course; 设置前进方向 0表示北 90东 180南 270西 location.horizontalAccuracy; 水平精准度 location.verticalAccuracy; 垂直精准度 location.timestamp; 定位信息返回的时间 location.speed; 设备移动速度 单位是米/秒, 适用于行车速度而不太适用于不行 */ CLLocation *location = [locations lastObject]; NSLog(@"%f,%f",location.coordinate.latitude,location.coordinate.longitude); // 获取到位置信息之后就会调用(调用频率非常高).如果只需要获取一次, 就要在这里设置停止 // [self.mgr stopUpdatingLocation]; }
iOS7只要开始定位, 系统就会自动要求用户对你的应用程序授权. 但是从iOS8开始, 想要定位必须先"自己""主动"要求用户授权.在iOS8中不仅仅要主动请求授权, 而且必须再info.plist文件中配置一项属性才能弹出授权窗口,value值可以随意写.eg:iOS7也可以添加,但不强制。
Privacy - Location Usage Description(iOS7)
NSLocationWhenInUseDescription,允许在前台获取GPS的描述
NSLocationAlwaysUsageDescription,允许在后台获取GPS的描述
if([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0) { NSLog(@"是iOS8"); // 主动要求用户对我们的程序授权, 授权状态改变就会通知代理 [self.mgr requestAlwaysAuthorization]; // 请求前台和后台定位权限 // [self.mgr requestWhenInUseAuthorization]; // 请求前台定位权限 } //iOS8中需要额外添加在个代理方法 #pragma mark - CLLocationManagerDelegate - (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status { /* 用户从未选择过权限 kCLAuthorizationStatusNotDetermined 无法使用定位服务,该状态用户无法改变 kCLAuthorizationStatusRestricted 用户拒绝该应用使用定位服务,或是定位服务总开关处于关闭状态 kCLAuthorizationStatusDenied 已经授权(废弃) kCLAuthorizationStatusAuthorized 用户允许该程序无论何时都可以使用地理信息 kCLAuthorizationStatusAuthorizedAlways 用户同意程序在可见时使用地理位置 kCLAuthorizationStatusAuthorizedWhenInUse */ if (status == kCLAuthorizationStatusNotDetermined) { NSLog(@"等待用户授权"); }else if (status == kCLAuthorizationStatusAuthorizedAlways || status == kCLAuthorizationStatusAuthorizedWhenInUse) { NSLog(@"授权成功"); // 开始定位 [self.mgr startUpdatingLocation]; }else { NSLog(@"授权失败"); } }
1.// 设置多久获取一次(单位是米,超出多米就开始调用) self.mgr.distanceFilter = 500; 2.// 设置获取位置的精确度 /* kCLLocationAccuracyBestForNavigation 最佳导航 kCLLocationAccuracyBest; 最精准 kCLLocationAccuracyNearestTenMeters; 10米 kCLLocationAccuracyHundredMeters; 百米 kCLLocationAccuracyKilometer; 千米 kCLLocationAccuracyThreeKilometers; 3千米 */ self.mgr.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
// 上一次的位置 @property (nonatomic, strong) CLLocation *previousLocation; // 总路程 @property (nonatomic, assign) CLLocationDistance sumDistance; // 总时间 @property (nonatomic, assign) NSTimeInterval sumTime; #pragma mark - CLLocationManagerDelegate - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { // 获取当前的位置 CLLocation *newLocation = [locations lastObject]; if (self.previousLocation != nil) { // 计算两次的距离(单位时米) CLLocationDistance distance = [newLocation distanceFromLocation:self.previousLocation]; // 计算两次之间的时间(单位只秒) timestamp 当前获取到为止信息的时间 NSTimeInterval dTime = [newLocation.timestamp timeIntervalSinceDate:self.previousLocation.timestamp]; // 计算速度(米/秒) CGFloat speed = distance / dTime; // 累加时间 self.sumTime += dTime; // 累加距离 self.sumDistance += distance; // 计算平均速度 CGFloat avgSpeed = self.sumDistance / self.sumTime; NSLog(@"距离%f 时间%f 速度%f 平均速度%f 总路程 %f 总时间 %f", distance, dTime, speed, avgSpeed, self.sumDistance, self.sumTime); } // 纪录上一次的位置 self.previousLocation = newLocation; }
// 1.添加指南针图片 UIImageView *iv = [[UIImageView alloc] initWithImage: [UIImage imageNamed:@"bg_compasspointer"]]; iv.center = CGPointMake(self.view.center.x, self.view.center.y); [self.view addSubview:iv]; self.compasspointer = iv; #pragma mark - CLLocationManagerDelegate // 当获取到用户方向时就会调用 - (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading { /* magneticHeading 设备与磁北的相对角度;trueHeading 设置与真北的相对角度 必须和定位一起使用, 一般使用磁北 顺时针 正 逆时针 负数 */ // 1.将获取到的角度转为弧度 = (角度 * π) / 180; CGFloat angle = newHeading.magneticHeading * M_PI / 180; // 2.旋转图片 效果不好,建议使用核心动画 self.compasspointer.transform = CGAffineTransformMakeRotation(-angle); }
- (void)viewDidLoad { [super viewDidLoad]; self.mgr.delegate = self; // 注意:如果是iOS8, 想进行区域检测, 必须自己主动请求获取用户隐私的权限.像CoreLocation的iOS8使用一样,需要在info添加权限,如NSLocationAlwaysUsageDescription if ([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0 ) { [self.mgr requestAlwaysAuthorization]; } // 开始检测用户所在的区域 //1.创建区域 /*CLRegion 有两个子类是专门用于指定区域的 一个可以指定蓝牙的范围CLBeaconRegion/ 一个是可以指定圆形的范围CLCircularRegion */ //创建圆形区域, 指定区域中心点的经纬度, 以及半径、标识 CLLocationCoordinate2D center = CLLocationCoordinate2DMake(40.058501, 116.304171); CLCircularRegion *circular = [[CLCircularRegion alloc] initWithCenter:center radius:500 identifier:@"软件园"]; //2.开始监听 [self.mgr startMonitoringForRegion:circular]; } #pragma mark - CLLocationManagerDelegate // 进入监听区域时调用 - (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region { NSLog(@"进入监听区域时调用"); } // 离开监听区域时调用 - (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region { NSLog(@"离开监听区域时调用"); }
这个方法只需要头文件声明#import <CoreLocation/CoreLocation.h>。而与以上方法不同,是不需要实现代理,只需要简单实现编码对象的方法
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { //1.创建地理编码对象 CLGeocoder *geocoder = [[CLGeocoder alloc] init]; // 2.利用地理编码对象编码 // 根据传入的地址获取该地址对应的经纬度信息 [geocoder geocodeAddressString:@"beijing" completionHandler:^(NSArray *placemarks, NSError *error) { if (placemarks.count == 0 || error != nil) { return ; } // placemarks地标数组, 地标数组中存放着地标, 每一个地标包含了该位置的经纬度以及城市/区域/国家代码/邮编等等..。 for (CLPlacemark *placemark in placemarks) { NSLog(@"name:%@ addressDictionary:%@ latitude:%f longitude:%f", placemark.name, placemark.addressDictionary, placemark.location.coordinate.latitude, placemark.location.coordinate.longitude); NSArray *address = placemark.addressDictionary[@"FormattedAddressLines"]; //遍历数组,读取插入字符串 NSMutableString *strM = [NSMutableString string]; for (NSString *str in address) { [strM appendString:str]; } NSLog(@"strm:%@",strM); } }]; }
和地位编码一样,只需要简单导入头文件
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { //1.创建地理编码对象 CLGeocoder *geocoder = [[CLGeocoder alloc] init]; CLLocation *location = [[CLLocation alloc] initWithLatitude:23.0f longitude:112.9f]; [geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) { for (CLPlacemark *placemark in placemarks) { NSLog(@"name:%@ \n addressDictionary:%@ \n latitude:%f \n longitude:%f \n locality:%@", placemark.name, //具体位置 placemark.addressDictionary, //地理位置详细信息 placemark.location.coordinate.latitude, //经度 placemark.location.coordinate.longitude, //纬度 placemark.locality); //城市名字 } }]; }
同样iOS8需要在info添加权限
#import "INTULocationManager.h" - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { // 1.创建位置管理者 INTULocationManager *mgr = [INTULocationManager sharedInstance]; // 2.利用位置管理者获取位置 /* INTULocationAccuracy 精确度,包括更新的位置和时间 timeout 延时时间 status 发送状态 */ [mgr requestLocationWithDesiredAccuracy:INTULocationAccuracyRoom timeout:5 delayUntilAuthorized:YES block:^(CLLocation *currentLocation, INTULocationAccuracy achievedAccuracy, INTULocationStatus status) { if (status == INTULocationStatusSuccess) { NSLog(@"获取位置成功 %f %f", currentLocation.coordinate.latitude , currentLocation.coordinate.longitude); }else if(status == INTULocationStatusError) { NSLog(@"获取失败"); } }]; }