學習定位,首先要了解它的含義,了解它的具體實現方法:下面介紹具體介紹它。
一:介紹
1、定位要使用CoreLocation框架
2、功能
(1)基礎定位
(2)地理編碼(文字轉換成地理位置) 反編碼(把經緯度轉換成地名)
3、iOS8 iOS9之后的改變
iOS8 的改變
(1)(添加了)定位服務的目的(在Info.plist中填寫)
《1》NSLocationAlwaysUsageDescription
《2》NSLocationWhenInUseUsageDescription
《3》如果忘記寫就不能使用 定位功能 沒有提示信息
(2)請求用戶授權
<1> requestAlwaysAuthorization
<2> requestWhenInUseAuthorization
<3> 如果和描述的目的不匹配 也不能使用定位功能
iOS9的改變
iOS9 按Home鍵 進入后臺 如果需要繼續定位
<1> 在info.plist 添加 Required background modes->App registers for location updates 如果不添加這對鍵值 卻使用后臺定位功能 系統會直接崩潰
<2> allowsBackgroundLocationUpdates 需要同時設置成YES
二:使用
1、使用定位服務所需的相關類和其他數據類型
(1)CLLocationManager
定位的管理者 可以通過這個類創建定位服務的功能
(2)CLLocation:地理位置信息相關的類
(3)CLLocationCoordinate2D:經緯度(坐標)信息的一個數據類型(是一個結構體)
(4)CLRegion:表示范圍的一個類
(5)CLGeocoder:地理編碼 反地理編碼的類
(6)CLPlacemark:表示地標的類 用文字表示位置信息的類(里面同時包含了location)
(7)CLHeading:表示導航方向的類 航向
(8)CLCircularRegion 圓形區域
(9)CLLocationDistance:距離
2、具體使用
(1)定位
<0> 檢查用戶是否在設置中 打開了定位服務
<1> 初始化定位對象
<2> info中添加描述使用定位的目的 并向用戶申請授權
<3> 掛上代理 并實現代理方法
<4> 如果需要使用后臺定位服務需要在 info中添加Required background modes 這個KEY以及它里面的元素App registers for location updates
<5> 開始定位
下面具體代碼實現定位:
// ViewController.m
// 3.7 定位
//
// Created by 記憶 on 16/3/7.
// Copyright ? 2016年 Remeber. All rights reserved.
//
#import "ViewController.h"
#import <CoreLocation/CoreLocation.h>
@interface ViewController ()<CLLocationManagerDelegate>
{
CLLocationManager *locationManager;
UILabel *speedLabel;
UILabel *distanceLabel;
UILabel *timeLabel;
UILabel *avgSpeedLabel;
CLLocation *lastLoc;//上一次更新的位置
BOOL isFirst;//標記 是否是第一次 定位
CLLocationDistance allDistance;//總距離
NSTimeInterval allTime;//總時間
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
isFirst = YES;
for (int i = 10; i<14; i++) {
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(10, 100+45*(i-10), CGRectGetWidth(self.view.frame)-20, 40)];
label.tag = i;
label.backgroundColor = [UIColor lightGrayColor];
label.textAlignment = NSTextAlignmentCenter;
[self.view addSubview:label];
}
speedLabel = [self.view viewWithTag:10];
distanceLabel = [self.view viewWithTag:11];
timeLabel = [self.view viewWithTag:12];
avgSpeedLabel = [self.view viewWithTag:13];
// 0、判斷 用戶是否 在《設置》里面 打開了 位置服務功能
if (![CLLocationManager locationServicesEnabled]) {
NSLog(@"用戶打開了 位置服務功能");
/*
// 1、跳彈出框 提示用戶打開步驟
// 2、通過代碼 跳出設置頁面
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"溫馨提示" message:@"請在設置中打開定位功能" preferredStyle:UIAlertControllerStyleAlert];
[alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
}]];
[self presentViewController:alertController animated:YES completion:nil];
*/
// openURL:用于跳轉app 跳到iOS允許跳到的頁面
// [[UIApplication sharedApplication]openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
// 判斷是否可以打開 能打開就跳到設置頁面
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]]) {
// 跳轉到 設置頁面
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
};
return;
}
// 1、創建定位管理者的對象
locationManager = [[CLLocationManager alloc]init];
// 多少米 去更新一次位置信息
locationManager.distanceFilter = 10;
// 設置位置的精準度
locationManager.desiredAccuracy = 10;
// 2、info中添加描述使用定位的目的 并向用戶申請授權
[locationManager requestWhenInUseAuthorization];
// 3、掛上代理 并實現代理方法
locationManager.delegate = self;
// 4、是否使用后臺定位的功能
locationManager.allowsBackgroundLocationUpdates = YES;
// 5、開始定位
[locationManager startUpdatingLocation];
}
//兩個代理方法
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray<CLLocation *> *)locations{
// bug -> 第一次 得到的距離 是負數 錯誤
// 錯誤原因:第一次的時候 lastLoc 是空的
// 定位代理方法的觸發:
// 第一次 定位當前位置
// 第二次定位 走了100之后 再次定位
// 真正有效的距離是
// 1-2 2-3 ...
// 位置信息
CLLocation *curLoc = locations.firstObject;
// 解決辦法
// 跳過第一次更新 直接把第一次更新的loc賦給lastLoc
if (isFirst == YES) {
isFirst =NO;
lastLoc = curLoc;
return;
}
// 坐標:經緯度 -> struct 結構體
// latitude:緯度
// longitude:經度
CLLocationCoordinate2D coordinate = curLoc.coordinate;
NSLog(@"經度:%f 緯度:%f",coordinate.longitude,coordinate.latitude);
// cllocationDistance -> double
NSLog(@"高度:%f",curLoc.altitude);
// 可以通過水平精準度 來判斷是否定位成功
// 如果是負數 表示 定位錯誤
NSLog(@"水平精準度%f",curLoc.altitude);
NSLog(@"垂直精準度:%f",curLoc.verticalAccuracy);
/*
course當前設備前進的方向
0°表示向北
90°表示向東
180°表示向南
270°表示向西
*/
NSLog(@"航向:%f",curLoc.course);
// 當前行駛速度
NSLog(@"速度:%f",curLoc.speed);
// floor 樓層的高度 -> level 幾層
NSLog(@"%ld",curLoc.floor.level);
// 當前定位的日期NSData
NSLog(@"當前的定位日期:%@",curLoc.timestamp);
// 1、是否超速
// speed > 要求的速度
speedLabel.text = curLoc.speed>=30 ? [NSString stringWithFormat:@"您已超速 當前速度%0.1f",curLoc.speed]:@"您在安全駕駛";
// 3、行駛距離
// 總距離 = 每一次更新位置得到的距離累加
// 更新位置得到的距離=上一次的loc 和當期的loc
// CLLocationDistance ->double
// 得到兩次loc之間的距離方法:
// - (CLLocationDistance)getDistanceFrom:(const CLLocation *)location
//得到兩次更新 位置信息 之間的距離
CLLocationDistance distance = [curLoc distanceFromLocation:lastLoc];
NSLog(@"兩次之間的距離:%f",distance);
allDistance += distance;
distanceLabel.text = [NSString stringWithFormat:@"您總共行駛了%0.1f米",allDistance];
//
// 4、行駛時間
// 總時間 = 每一次更新 得到的時間間隔的累加
// 可以得到當期的時間戳
// 日期有一個方法 計算兩個日期之間的時間間隔
//
// - (NSTimeInterval)timeIntervalSinceDate:(NSDate *)anotherDate
// ?上一次時間 -> 通過記錄 上一次更新的location來得到
allTime += [curLoc.timestamp timeIntervalSinceDate:lastLoc.timestamp];
int hours = allTime/3600;
int min = (int)allTime%3600/60;
int sec = (int)allTime%3600%60;
timeLabel.text = [NSString stringWithFormat:@"您行駛了%d時%d分%d秒",hours,min,sec];
// 2、平均速度
// 總距離/總時間
avgSpeedLabel.text = [NSString stringWithFormat:@"平均速度每秒%0.1f",allDistance/allTime];
// 將要出 定位的代理方法的時候 curLoc沒有用了
// 把curLoc 變成了 上一次的 位置信息
// 賦給 lastLoc
lastLoc = curLoc;
}
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error{
NSLog(@"error:%@",error);
}