使用CoreLocation框架進行定位
1. iOS8以前的定位
#import "ViewController.h"
// 0. 導入頭文件
#import <CoreLocation/CoreLocation.h>
@interface ViewController () <CLLocationManagerDelegate>
/** 位置管理者 */
@property (nonatomic, strong) CLLocationManager *manager;
@end
@implementation ViewController
- (CLLocationManager *)manager
{
if (!_manager) {
// 1. 建立CLLocationManager
_manager = [[CLLocationManager alloc] init];
// 2. 設置代理
_manager.delegate = self;
// 每隔多少米定位一次
_manager.distanceFilter = 100;
/**
kCLLocationAccuracyBestForNavigation // 最適合導航
kCLLocationAccuracyBest; // 最好的精確度,僅次於kCLLocationAccuracyBestForNavigation
kCLLocationAccuracyNearestTenMeters; // 附近10m
kCLLocationAccuracyHundredMeters; // 100m
kCLLocationAccuracyKilometer; // 1公里
kCLLocationAccuracyThreeKilometers; // 3公里
*/
// 設置定位精確度
// 並非精確度越高就越好,精確度越高,就越耗性能,越費電,要根據需求來設置精確度
_manager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
}
return _manager;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// 3.開始更新地址
// 此處重點:必定要在info.plist文件中加上key:Privacy - Location Usage Description,value能夠隨便寫
[self.manager startUpdatingLocation];
}
#pragma mark - 實現CLLocationManagerDelegate代理方法
// 4.實現代理方法
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
CLLocation *location = [locations lastObject];
NSLog(@"%@ -- %f", location.description, location.speed);
}
@end
- 注意點:第三步出,必定要在info.plist文件中加上key:Privacy - Location Usage Description,如圖所示:
2.iOS8的定位
- iOS8相對於以前的版本,蘋果進一步增強了對用戶隱私的保護。
當APP想訪問用戶的隱私信息時,系統再也不自動彈出一個對話框讓用戶受權
- 解決方案:
- (1)調用iOS 8.0的API,主動請求用戶受權
- -(void)requestAlwaysAuthorization // 請求容許在先後臺都能獲取用戶位置的受權
- -(void)requestWhenInUseAuthorization // 請求容許在前臺獲取用戶位置的受權
- (2)務必在info.plist文件中配置對應的鍵值, 不然以上請求受權的方法不生效
NSLocationAlwaysUsageDescription : 容許在先後臺獲取GPS的描述
NSLocationWhenInUseDescription : 容許在前臺獲取GPS的描述
#import "ViewController.h"
#import <CoreLocation/CoreLocation.h>
@interface ViewController () <CLLocationManagerDelegate>
/** 位置管理者 */
@property (nonatomic, strong) CLLocationManager *manager;
@end
@implementation ViewController
- (CLLocationManager *)manager
{
if (_manager == nil) {
_manager = [[CLLocationManager alloc] init];
_manager.delegate = self;
// 採起前臺定位
// 1. 須要在info.plist文件中添加key:NSLocationWhenInUseUsageDescription
// 2. 若是須要在後臺繼續定位,須要勾選後臺模式,當程序進入後臺後,會在最上方出現一個藍條
// [_manager requestWhenInUseAuthorization];
// 採用先後臺定位
// 1. 須要在info.plist文件中添加NSLocationAlwaysUsageDescription這個key
// 2. 這種模式的後臺定位,不須要勾選後臺模式,也不會出現藍條
[_manager requestAlwaysAuthorization];
// requestWhenInUseAuthorization和requestAlwaysAuthorization請求同時存在:
// 1. requestWhenInUseAuthorization請求在前,會先彈出前臺受權描述,第二次啓動程序的時候,還會彈出先後臺受權描述
// 2. requestAlwaysAuthorization在前,只會彈出先後臺受權描述,不會彈出前臺受權描述.
}
return _manager;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.manager startUpdatingLocation];
}
#pragma mark - <CLLocationManagerDelegate>
/**
* 更新定位
*
* @param manager 位置管理器
* @param locations 定位的位置數組
*/
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
NSLog(@"定位了");
}
3. iOS9 的定位
- 在iOS9中,若是使用requestWhenInUseAuthorization,跟iOS8同樣,不只須要設置info.plist,若是想要在後臺定位,也須要勾選後臺模式,還須要設置allowsBackgroundLocationUpdates=Yes.一樣也會出現藍條
_manager.allowsBackgroundLocationUpdates = YES;
- iOS 9.0 能夠單次請求用戶位置:-(void)requestLocation
- 做用是按照定位的精確度從低到高進行排序,逐個進行定位.若是獲取到的位置不是精確度最高的那個,也會在定位超時後,經過代理告訴外界(必須實現代理的-locationManager:didFailWithError:方法, 不能與startUpdatingLocation方法同時使用)
- (void)requestLocation
-(void)locationManager:(nonnull CLLocationManager *)manager didUpdateLocations:(nonnull NSArray<CLLocation *> *)locations // 成功調用
-(void)locationManager:(nonnull CLLocationManager *)manager didFailWithError:(nonnull NSError *)error // 失敗調用
4. CLLocation
- 以一個小的需求來學習CLLocation
- 一個小需求:打印當前用戶的行走方向,偏離角度以及對應的行走距離, 例如:」北偏東30度方向,移動了8米」
/**
* 代理方法: 更新定位
*
* @param manager 位置管理器
* @param locations 定位的位置數組
*/
- (void)locationManager:(nonnull CLLocationManager *)manager didUpdateLocations:(nonnull NSArray<CLLocation *> *)locations
{
// CLLocation經常使用屬性
// coordinate (當前位置所在的經緯度)
// altitude (海拔)
// speed (當前速度)
// course (航向)
// -distanceFromLocation (獲取兩個位置之間的直線物理距離)
CLLocation *location = [locations lastObject];
// 1. 獲取偏向角度
NSString *angleStr = nil;
switch ((int)location.course / 90) {
case 0:
angleStr = @"北偏東";
break;
case 1:
angleStr = @"東偏南";
break;
case 2:
angleStr = @"南偏西";
break;
case 3:
angleStr = @"西偏北";
break;
default:
angleStr = @"未知位置";
break;
}
// 2. 偏移角度
NSInteger angle = (int)location.course % 90;
if (angle == 0) { // 表示正方向
angleStr = [angleStr substringWithRange:NSMakeRange(0, 1)];
}
// 3. 移動了多少米
double distance = 0;
if (_oldLocation) {
distance = [location distanceFromLocation:_oldLocation];
}
_oldLocation = location;
// 4. 打印
NSString *locationStr = [NSString stringWithFormat:@"%@%zd度方向,移動了%.2fm", angleStr, angle, distance];
NSLog(@"%@", locationStr);
}
5.定位的其餘補充
kCLAuthorizationStatusNotDetermined = 0, // 用戶未決定
kCLAuthorizationStatusRestricted, // 受限制
kCLAuthorizationStatusDenied, // 拒絕
kCLAuthorizationStatusAuthorizedAlways NS_ENUM_AVAILABLE(NA, 8_0), // 永久受權
kCLAuthorizationStatusAuthorizedWhenInUse NS_ENUM_AVAILABLE(NA, 8_0), // APP使用的時候受權