iOS 自带定位服务
2016-01-11 10:51
507 查看
原文地址:http://cnbin.github.io/blog/2015/07/04/ios-zi-dai-ding-wei-fu-wu/
定位服务
iOS 7 提供了4种不同的途径进行定位,具体如下所示。Wi-Fi。通过 Wi-Fi 路由器的地理位置信息查询,比较省电。iPhone、iPod touch 和 iPad 都可以采用这种方式定位。
蜂窝式移动电话基站。通过移动运用商基站定位。只有 iPhone、3G 版本的 iPod touch和iPad可以采用这种方式定位。
GPS 卫星。通过 GPS 卫星位置定位,这种方式最为准确,但是耗电量大,不能遮挡。iPhone、iPod touch 和 iPad 都可以采用这种方式定位。
iBeacon 微定位。iOS 7支持iBeacon技术,iBeacon 技术是苹果公司研发的,它使用低功耗蓝牙技术,通过多个 iBeacon 基站可以创建一个信号区域(地理围栏),当设备进入该区域时,相应的应用程序便会提示用户进入了这个地理围栏。
在对定位服务编程时,iOS 不像 Android 系统可以指定采用哪种途径进行定位。iOS 的 API 把底层这些细节屏蔽掉了,开发人员和用户并不知道现在设备是采用哪种方式进行定位的(微定位除外),iOS 系统会根据设备的情况 和周围的环境采用一套最佳的解决方案。
也就是说,如果能够接收 GPS 信息,那么设备优先采用 GPS 定位,否则采用Wi-Fi 或蜂窝基站定位。在 Wi-Fi 和蜂窝基站之间,优先使用 Wi-Fi,如果无法连接 Wi-Fi 才使用蜂窝基站定位。
定位服务编程
在 iOS 7 中,定位服务有比较大的变化,主要使用 Core Location框架,定位时主要使用 CLLocationManager、 CLLocationManagerDelegate 和 CLLocation 这3个类,下面简要介绍一下它们。
CLLocationManager。用于定位服务管理类,它能够给我们提供位置信息和高度信息,也可以监控设备 进入或离开某个区域,还可以获得设备的运行方向等。
CLLocationManagerDelegate。它是 CLLocationManager 类的委托协议。
CLLocation。该类封装了位置和高度信息。
在定位服务的应用中,第一次请求位置信息时,系统会提示用户是否允许开启定位服务。如图所示,用户所在的位置是比较私 密的信息,应用获取这些信息时,用户是有知情权和否定权的。如果应用在用户不知情的情况下获得其位置信息,这在某些国家是违法的。
如果用户“不允许”,定位服务就无法获得位置信息了。如果想改变这些设置,可以在系统“设置”应用中 开启或关闭,如图所示。
如图所示,我们可以关闭所有的定位服务,此时只需关闭最上面的“定位服务”开关控件就可以了。 当然,也可以关闭或开启下面的具体应用。
在应用启动进入界面时,会获得位置信息,并显示在对应的文本框中。如果设备位置发生变化,也会重新获取位置信息,并更新对应的文本框。
首先,为工程引入
Core Location框架,具体步骤是选择工程中的
TARGETS→WhereAmI→Build Phases→Link Binary With Libraries,选择右下角的
+按钮,打开“选择要添加的框架和库”对话框,如图所示。
ViewController.h 中的代码如下:
在上述代码中,我们首先引入了
CoreLocation/CoreLocation.h和
CoreLocation/CLLocationManagerDelegate.h这两个头文件,然后在定义
ViewController时声明了
CLLocationManagerDelegate协议。此外,我们还定义了
CLLocationManager *locationManager属性。 在 ViewController.m 中,viewDidLoad 方法的代码如下:
- (void)viewDidLoad { [super viewDidLoad]; //初始化定位服务管理对象 _locationManager = [[CLLocationManager alloc] init]; _locationManager.delegate = self; _locationManager.desiredAccuracy = kCLLocationAccuracyBest; (1) _locationManager.distanceFilter = 1000.0f; (2) }
在上述代码中,我们主要对
CLLocationManager的成员变量
_locationManager进行了初始化。首先,使用
[[CLLocationManager alloc] init]语句实例化
CLLocationManager对象,然后使用
_locationManager. delegate = self语句设置定位服务委托为 self。
第(1)行代码设置
desiredAccuracy属性,它是一个非常重要
的属性,其取值有6个常量,具体如下所示。
kCLLocationAccuracyNearestTenMeters。精确到10米。
kCLLocationAccuracyHundredMeters。精确到100米。
kCLLocationAccuracyKilometer。精确到1000米。
kCLLocationAccuracyThreeKilometers。精确到3000米。
kCLLocationAccuracyBest。设备使用电池供电时最高的精度。
kCLLocationAccuracyBestForNavigation。导航情况下最高的精度,一般有外接电源时才能使用。
精度越高,请求获得位置信息的时间就越短,这就意味着设备越耗电,因此一个应用应该选择适合它的精度。 如果你的应用是一个车载导航应用,
kCLLocationAccuracyBestForNavigation是比较好的选择,你可以使用汽车上的电瓶为设备供电。
如果你的应用是为徒步旅行者提供的导航应用,
kCLLocationAccuracyHundredMeters是一个不错的选择。
第(2)行代码设置
distanceFilter属性,它是距离过滤器,定义了设备移动后获得位置信息的最小距离,单位是米,本例设置为1000米。
初始化 CLLocationManager 类后,需要使用
startUpdatingLocation方法开始定位服务,该方法定义在
ViewController.m的
viewWillAppear:方法中。viewWillAppear:方法的代码如下:
- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; //开始定位 [_locationManager startUpdatingLocation]; }
调用
startUpdatingLocation方法时,就会开启定位服务。根据设定的条件,它不断请求回调新的位置信息。因此,开启这个方法一定要慎重,在视图控制器的声明周期方法
viewWillAppear:中使用这个方法是最合适的。与开启服务对应的方法是
stopUpdatingLocation方法,它是在视图控制器的
viewWillDisappear:方
法中调用的。
viewWillDisappear:方法的代码如下:
- (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; //停止定位 [_locationManager stopUpdatingLocation]; }
这个方法在视图消失(应用退到后台)时调用,能够保证最及时地关闭定位服务。在iOS 6中,请求有所变化, 定位服务应用退入台后,可以延迟更新位置信息,这可以通过
allowDeferredLocationUpdatesUntil- Traveled:timeout:方法实现。要关闭延迟更新,可以使用
disallowDeferredLocationUpdates方法实现。
此外,在iOS 6中,新增了
pausesLocationUpdatesAutomatically属性,它能设定自动暂停位置更新,而把
定位服务的开启和暂停管理权交给系统,这样会更加合理和简单。
一旦定位服务开启,并设置好
CLLocationManager委托属性
delegate 后,当用户设备移动到达过滤距离时, 就会回调委托方法。与定位服务有关的方法有如下两个。
locationManager:didUpdateLocations:。定位成功。这是iOS 6中新增的方法,替代了之前的
locationManager:didUpdateToLocation:fromLocation:方法。
locationManager:didFailWithError:。定位失败。
实现 CLLocationManager 委托的代码如下:
#pragma mark Core Location委托方法用于实现位置的更新 - (void)locationManager:(CLLocationManager *)manager didUpdateLocations: (NSArray *)locations { CLLocation * currLocation = [locations lastObject]; (1) _txtLat.text = [NSString stringWithFormat:@"%3.5f",currLocation.coordinate.latitude]; (2) _txtLng.text = [NSString stringWithFormat:@"%3.5f",currLocation.coordinate.longitude]; (3) _txtAlt.text = [NSString stringWithFormat:@"%3.5f",currLocation.altitude]; (4) } - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error { NSLog(@"error: %@",error); }
在
locationManager:didUpdateLocations:方法中,参数
locations是位置变化的集合,它按照时间变化的顺序存放。如果想获得当前设备的位置,可以使用
第(1)行中的
[locations lastObject]语句获得集合中的最后一个元素,它就是设备的当前位置了。从集合中返回的对象类型是 CLLocation,CLLocation 封装了位置、高度等信息。在上面的代码中,我们使用了它的两个属性
altitude和
coordinate,其中前者是高度值,后者是封装经度和纬度的结构体
CLLocationCoordinate2D。
CLLocationCoordinate2D的定义如下:
typedef struct { CLLocationDegrees latitude; //纬度 CLLocationDegrees longitude; //经度 } CLLocationCoordinate2D;
其中
latitude为纬度信息,
longitude为经度信息,它们都是
CLLocationDegrees类型。
CLLocationDegrees是使用
typedef定义的
double类型。
第(2)行代码中的
currLocation.coordinate.latitude表达式用于获得设备当前的纬度,
第(3)行代码中的
currLocation.coordinate.longitude表达式用于获得设备当前的经度,
第(4)行代码中的
currLocation. altitude表达式用于获得高度。
关于定位服务的测试
一般情况下,定位服务应用的测试和运行有两个选择:模拟器和设备。原则上,我们先通过模拟器,然后再 使用设备测试。由于定位服务的特点,使用设备测试时我们需要到现场进行测试,所以有的时候有一定的局限性。 因此,使用模拟器测试有的时候是不可替代的。在 Xcode 早期版本中,模拟器是不能模拟位置信息的变化的,请求获取位置信息只是固定苹果公司总部地址。 而现在的 Xcode 版本预先设置了几个地址,我们可以模拟改变位置。如果想让模拟器一开始运行的时候就能够获 得模拟数据,可以在启动参数中设置。首先,在 Xcode 工具的左上角编辑应用的
Scheme,如图所示。
选择
Edit Scheme菜单后,弹出如图所示的对话框,从中选择
Run WhereAmI.app→Options,在
Core Location项目中选中
Allow Location Simulation复选框,然后在下面的
Default Location下拉框中选择你感兴趣的城市。
这样应用启动时,就会模拟定位到你选择的城市了。如果列表中没有我们需要的地点,可以使用最下面的
Add GPX File to Project菜单项为工程添加一个
GPX1文件。下面是
GPX 文件的内容:
<?xml version="1.0" encoding="UTF-8" standalone="no" ?> <gpx xmlns="http://www.topografix.com/GPX/1/1" creator="MyGeoPosition.com" version="1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd"> <wpt lat="40.002240" lon="116.323328"> <name>中国北京 东城区北京站东街北京 邮政编码: 100005</name> <src>MyGeoPosition.com</src> <link>http://mygeoposition.com</link> </wpt> </gpx>
<wpt>标签中的
lat属性设置纬度,
lon属性设置经度。自己手写这个文件还是比较麻烦的,一般使用 http://www.mygeoposition.com 网站提供的
GPX工具工具生成。这个网站免费提供地理信息编码和反编码、生成
KML 和 GPX 文件等服务。
GPX(GPS eXchange Format,GPS交换格式)是一个 XML 格式,是为应用软件设计的通用 GPS 数据格式。
得到 GPX 文件后,可以通过如图所示的
Add GPX File to Project菜单项将它添加到 Xcode 工程中,此时在菜单中就会出现
GPX文件了。如果我添加的文件名是
test.gpx,则在菜单中出现
test 菜单项,选择 test 即可使用这个模拟坐标数据了。
如果在应用启动参数中没有设置初始的模拟位置数据,我们还可以在运行之后设置。在调试工具栏中选择模 拟定位按钮,即可选择模拟位置,如图所示。
Xcode 中的模拟器还提供了连续位置变化测试能力。如果想开发导航应用,这个功能对我们有很大的帮助。 此外,模拟器有几个固定的模式,可以发出连续变化的位置数据。打开模拟菜单的“调试”→“位置”,可以发 现共有7个菜单项,
其中后面3个都能发出连续的位置变化数据,它们的起始点从苹果公司总部开始,按照一个固定的线路运动,这三者的区别是
City Bicycle Ride是最慢的,
City Run要快一些,
Freeway Drive最快。
相关文章推荐
- iOS自定义Tabbar
- IOS学习笔记之网格视图
- iOS性能优化之内存管理:Analyze、Leaks、Allocations的使用和案例代码
- 分享一下我封装iOS自定义控件的体会,附上三个好用的控件Demo &lt;时间选择器&amp;多行输入框&amp;日期选择器&gt;
- iOS中PCH文件的配置
- iOS多线程的初步研究(十)-- dispatch同步
- iOS个人开发Tips
- iOS多线程的初步研究(九)— dispatch源
- iOS多线程的初步研究(八)-- dispatch队列
- iOS block的使用
- ios layer的学习
- iOS多线程的初步研究(七)-- dispatch对象
- iOS多线程的初步研究(六)-- NSOperation
- iOS多线程的初步研究(五)-- 如何让NSURLConnection在子线程中运行
- iOS多线程的初步研究(四)-- NSTimer
- 2015年最新苹果开发者账号注册流程详解
- ios数组字典混合运用
- ios字典存到数组当中进行年龄降序排序,然后删除指定的成员信息
- iOS端实现「节日换肤」通用技术方案(无需更新程序)
- iOS多线程的初步研究(三)-- NSRunLoop