ios定位功能的实现
学习定位,首先要了解它的含义,了解它的具体实现方法:下面介绍具体介绍它。
一:介绍
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);
}
22.png