来源:Getting the User’s Location
- 标准位置服务,提供了高度可配置的方式来获取当前位置并且跟踪改变.
- 区域监控让你可以监控定义的地理区域和蓝牙信标.(蓝牙只在iOS上有效)
- The significant-change location service提供了当大的位置变动时,通知并得到当前位置.正确的使用它可以避免免费太多的电量.
要求在iOS App里使用定位服务
在app里的info.plist
文件里包含UIRequiredDeviceCapabilities
键.App Store用在这个键里的信息来确定是否可以被下载,如果没有列表里的功能就不能被下载.
UIRequiredDeviceCapabilities
的值,是标识功能的字符串所组成的数组,这些功能应该是被app所需要的.有两个相关定位服务的字符串:
- 如果你需要定位服务,请包含
location-services
字符串. - 如果您的应用需要GPS硬件提供的精度,请包含gps字符串.
重要:如果你的iOS app在没有上述的字符串也能正确使用定位服务,那就不在
UIRequiredDeviceCapabilities
包含它们
获得用户的当前位置
Core Location framework 可以让你位置设备的当前位置并在app里使用它们.你可以配置定位服务,让framework来报告设备的位置,也可以周期性的更新数据.
两个服务可以让你得到用户的当前位置:
- 标准定位服务:得到定位数据,并以指定的精度水平跟踪定位的改变
- significant-change定位服务:只有当在设备有重大的位置改变时才会通知,比如说500或以上.
收集定位信息是一项很耗电量的操作.你应该选择合适的定位服务,避免消耗电量.举例:
- 如果你的iOS app即使在后台也要持续的跟踪定位,使用准备定位服务并指明
UIBackgroundModes
,让app可以在后台也可继续的运行和接收定位数据.(在这种情况下,你应该保证设置 location manager的pausesLocationUpdatesAutomatically
属性为true
,来节省电量.) - 如果你不需要GPS级别的精度,并且你不需要持续的跟踪,你可以使用significant-change定位服务.正确的使用这个服务是非常重要的,因为你至少15分钟会唤醒系统和你的app,即使没有位置的改变,并且在你停止它之前会持续的运行.
查看定位服务是否有效
以下几点会让定位无效:
- 用户在Settings或系统偏好里关闭了定位服务.
- 用户拒绝和指定app的定位服务.
- 设备在飞行模式下,无法启动必要的设备
基于以上的理由,在你要开始定位服务之前,你都要查看一下CLLocationManager
的类方法locationServicesEnabled
确保定位服务是开启的.如果返回的是false
,你又要开始定位服务,系统会让用户确认定位服务是否应该被开启.
开始标准定位服务
准备定位服务是得到用户位置的很普遍的方式,因为它在所有的iOS和OS X设备都有效.在你使用这个服务之前,你要配置定位数据所需的精度在移动要新位置之前所需的距离.当你开始服务之前,它会使用特定的属性去查明硬件是否有效,然后会持续的报告定位事件给你的app.这项服务适合于导航app,或高精度定位或周期性的更新流.
为了使用准备定位服务,创建CLLocationManager
类的一个实例,并且配置的desireAccuracy
和distanceFilter
属性.赋值了个delegate
并调用startUpdatingLoation
方法去开始定位通知.当定位数据变成有效时,location manager就会通知它的delegate
对象.当定位更新已经开始递送时,你可直接在CLLocationManager
对象获取最新的数据,而不用等新事件的递送.停止这种定位的更新,调用location manager对象的stopUpdatingLocation
方法.
- (void)startStandardUpdates
{
// Create the location manager if this object does not
// already have one.
if (nil == locationManager)
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyKilometer;
// Set a movement threshold for new events.
locationManager.distanceFilter = 500; // meters
[locationManager startUpdatingLocation];
}
开始 Significant-Change 定位服务
这个服务需要
kCLAuthorizationStatusAuthorizedAlways
授权状态.
- (void)startSignificantChangeUpdates
{
// Create the location manager if this object does not
// already have one.
if (nil == locationManager)
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
[locationManager startMonitoringSignificantLocationChanges];
}
停止服务
[locationManager stopMonitoringSignificantLocationChanges];
如果你的iOS app被挂起或终止,当新的数据来的时候,这个服务会自动唤醒你的app.在唤醒时候内,app会进入后台并且给你一小段时间(大概10秒)去手动重启定位服务并处理定位数据.(在任何定位递送之前你必须要重启定位服务Knowing When to Start Location Services),因为你的app是在后台的,你必须做最少的事情,并且避免做任何在预计时间内得不到答案的任务(比如:network).否则,你的app会被终止.如里你需要更多的后台运行时间去处理位置数据,它可以用UIApplication
类的beginBackgroundTaskWithName:expirationHandler:
去请求很多的后台运行时间.
当用户不管是全局还是在你的app里关闭了后台app刷新,significant-change定位服务不会重启你的app.更进一步,即使你在前台,app也不会接收到significant-change或区域跟踪事件.
从服务器那里接收定位数据
不论是准备定位服务还是significant-change定位服务,接收定位事件方式是一样的.location manager是将事件报告给delegate
的locationManager:didUpdateLocations:
方法.如果有接收事件是有错误,location manager会调用delegate
的locationManager:didFailWithError:
方法.
因为location manager有时会返回缓存的事件(就是不是最新的),最好是检查一下定位的时间戳:
// Delegate method from the CLLocationManagerDelegate protocol.
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
// If it's a relatively recent event, turn off updates to save power.
CLLocation* location = [locations lastObject];
NSDate* eventDate = location.timestamp;
NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];
//这是15秒之外的就是旧数据,如果做导航的话可以更短.
if (abs(howRecent) < 15.0) {
// If the event is recent, do something with it.
NSLog(@"latitude %+.6f, longitude %+.6f\n",
location.coordinate.latitude,
location.coordinate.longitude);
}
}
使用时间戳名,还可以用精度来判断.
知道什么时候要开始定位服务
使用定位服务的app,不会自动开始这些服务.有一些例外情况,不要一些情况下开始定位服务,比如在启动的时候或者因一些原因定位服务不能被使用的时候.
一个app要使用Core Location必须要在info.plist
里包含NSLocationAlwaysUsageDescription
或NSLocationWhenInUseUsageDescription
键,并且设置一些字符串给它们,说明怎么使用定位数据.如果在你调用requestWhenInUseAuthorization
方法,但你没有设置以上那些键,系统就会忽略你的这些请求.
如果你在监控区域或使用significant-change定位服务,有一些情况是你必须在启动时候要开启定位服务的.可以终止使用这些服务的app,并在新的位置事件到达时随后重新启动.app自己重新启动的时候,定位服务不会自动开启.当你一个app因为定位更新而重新启动时,启动选项dictionary会被传到application:willFinishLaunchingWithOptions:
或application:didFinishLaunchingWithOptions:
里,使用的是UIApplicationLaunchOptionsLocationKey
键.该键的存在表明新的位置数据正在等待传送到您的应用程序.为了获取这些数据,你必须创建新的CLLocationManager
对象并重新开启定位服务.当你开始这些定位服务时,location manager会把所以待更新的定位数据发送给delegate
.
在后台获取定位事件(iOS only)
... ...
当你的app在后台时,推迟定位更新
... ...
网友评论