前言
当肾Phone出现,定位服务一直都是作为一个前沿技术跟中心存在。CL API在肾平台SDK第一次发布的时候就列入了公开接口。在每次新发布的iOS版本中,大苹果总是循序渐进的增加一些新功能到CL框架,比如后台定位,geocoding亦或是iBeacons。
iOS8义无反顾往前走。更其他领域的最新更新一样,CL已经动摇了,随着新设计允许让开发去创建之前他们无法完成的新东西的同时还帮助保护用户隐私。特别的,iOS8为CL框架带了3套主要的改变:更粗糙的授权,室内定位,还有访问监控。
授权
APP有多种原因像你获取地址信息授权。(此处省略各种原因举栗子)
iOS8以前,定位服务授权是二进制的:给或者不给。设置的应用选项会展示那些是你授权后台定位服务的APP,但是你除了完全授权使用定位服务外不能再做其他处理了(短暂使用)。
iOS8对这方面做了修正,有以下两种授权方式。
- 在APP在使用的时候授权
- 一直授权
这毫无疑问对用户隐私来说是一个利好,但是对于开发来说呵呵。。
请求授权
在早先的iOS,定位服务的授权请求是很隐式的。创建一个CLLocationManager
实例,如果用户还没有显示的同意或者拒绝一个APP的定位服务授权下面得代码会在触发探测用户授权定位服务。
import Foundation
import CoreLocation
let manager = CLLocationManager()
if CLLocationManager.locationServicesEnabled() {
manager.startUpdatingLocation()
}
为了让事情简单点,假设上述代码中我们已经声明了
manager
实例作为成员变量,并且也设置了它的代理。
每次让CLLocationManager
获取最新地址信息的动作都会弹出定位服务授权框。
在iOS8,请求授权与开始使用定位服务是两个不同的动作。特别地,这里有两个不同的方法你可以用来显式的请求授权requestWhenInUseAuthorization
和requestAlwaysAuthorization
。前者只是允许你在应用打开得时候获取地位位置信息。后者则允许一直在后台获取地理位置信息。
if CLLocationManager.authorizationStatus() == .NotDetermined {
manager.requestWhenInUseAuthorization()
}
或
if CLLocationManager.authorizationStatus() == .NotDetermined {
manager.requestAlwaysAuthorization()
}
因为授权动作是异步的,所以应用不能马上开始使用定位服务。相反,应用中必须实现locationManager:didChangeAuthorizationStatus
的代理方法,这个代理方法当用户改变当前的授权权限的时候将会被发送。
如果用户上一次授予用户定位服务的权限,这个代理方法将会在定位管理者被初始化之后并且它的代理被设置成正确的授权状态后被调用。这样将便于代码进行定位服务。
func locationManager(manager: CLLocationManager!,
didChangeAuthorizationStatus status: CLAuthorizationStatus)
{
if status == .AuthorizedAlways || status == .AuthorizedWhenInUse {
manager.startUpdatingLocation()
// ...
}
}
描述性字符串
另外一个变化是iOS8中要求使用定位服务。在过去,info.plist
中选择性包含一个NSLocationUsageDescription
的Key.这个值是在向用户申请定位服务的时候展示给用户看的一段字符串。现在被分割为了两个Keys(NSLocationWhenInUseUsageDescription and NSLocationAlwaysUsageDescription
),并且现在更加强制了;如果你调用了requestWhenInUseAuthorization or requestAlwaysAuthorization
而没有使用相对应得Key,那么这段提示不会展示给用户。
请求多次授权
另外一个值得注意的地方是授权弹出将只给用户展示一次。若CLLocationManager.authorizationStatus()
返回值不为NotDetermined
,此时调用requestWhenInUseAuthorization() or requestAlwaysAuthorization()
将不会给用户展示告警栏。在用户最初选择之后,唯一改变授权设置的方式是到设置里的用户隐私条款设置里面进行对应APP相关设置。
尽管在旧操作系统上有诸多不便,在一个应用的生命周期内最显著麻烦的事情主要是“使用权限”跟“永久权限”的请求。大苹果为了缓和这个状况,提出了字符串常量,UIApplicationOpenSettingsURLString
,提供了一个URL用来打开机器的设置界面。
这里是一个实例代码教你让APP打开设置界面获取永久权限:
switch CLLocationManager.authorizationStatus() {
case .Authorized:
// ...
case .NotDetermined:
manager.requestWhenAlwaysAuthorization()
case .AuthorizedWhenInUse, .Restricted, .Denied:
let alertController = UIAlertController(
title: "Background Location Access Disabled",
message: "In order to be notified about adorable kittens near you, please open this app's settings and set location access to 'Always'.",
preferredStyle: .Alert)
let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel, handler: nil)
alertController.addAction(cancelAction)
let openAction = UIAlertAction(title: "Open Settings", style: .Default) { (action) in
if let url = NSURL(string:UIApplicationOpenSettingsURLString) {
UIApplication.sharedApplication().openURL(url)
}
}
alertController.addAction(openAction)
self.presentViewController(alertController, animated: true, completion: nil)
}
往后兼容
所有新的API都已iOS8作为根本。对于仍然需要支持iOS7或更早版本,我们必须维护两个平行代码-一个是iOS8显示的索取权限和另外一个仅仅是要求获取地理位置信息更新。一个简单得实现如下:
func triggerLocationServices() {
if CLLocationManager.locationServicesEnabled() {
if self.manager.respondsToSelector("requestWhenInUseAuthorization") {
manager.requestWhenInUseAuthorization()
} else {
startUpdatingLocation()
}
}
}
func startUpdatingLocation() {
manager.startUpdatingLocation()
}
// MARK: - CLLocationManagerDelegate
func locationManager(manager: CLLocationManager!, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
if status == .AuthorizedWhenInUse || status == .Authorized {
startUpdatingLocation()
}
}
建立用户信任
在iOS8所有得改变上跑着共同的一条线索:那就是它们(改变)容易地获取用户的信任。
显式请求授权鼓励应用不要等到用户准备做某些事情需要授权的时候才去请求用户授权。(略)
大苹果尊重用户的个人选择。。。(略)
室内个人定位
当你细读CL框架的时候可能会对CLFloor对象产生疑惑,这个新对象有如下简单得接口:
class CLFloor : NSObject {
var level: Int { get }
}
就这么简单,一个简单属性,告诉你你现在在一个建筑的几楼。
欧洲人说底层是0楼不是1楼。。
一个CLLocationManager
返回的CLLocation
对象可能带有一个floor
属性,但是你若写一个使用定位服务的栗子APP你会发现你的CLLocation
对象中的floor
属性为nil
。
这是因为API改变是冰山的尖端以此来为iOS8带来一套新特征从而便利室内定位跟踪(我晕菜了)。对于开发者为大空间建筑物设计应用的时候,比如博物馆或者大型商场,大苹果提供了支持IPS的工具通过使用内置CL APIs和WiFi,GPS,蜂窝式网络,还有iBeacon数据混用的方式。
大概说了这个技术现状是商用上严格控制。。。
CLVisit
在很多应用,使用位置定位来判断用户是不是在某个期望的地理位置。概念上说,你会将这个行为想成名词“现场”或者是“访问”而不是原生的GPS定位。
略一段。。
在iOS8中,大苹果为我们解决此类问题提供了CLVisit
,一个新的后台定位监测类型。一个但一个的CLVisit
表示用户花了一段时间在一个单一的地方,包含了同一地理坐标以及起始/结束时间戳。
理论上来说,使用访问监控不会比其他的后台定位做更多的活儿。简单得调用manager.startMonitoringVisits()
可以启动后台访问定位,假设用户已经永久授权。一旦启动,你的APP将会被后台激活当有新的更新到来的时候(让我想到了乐动力这个APP)。与基础的定位不同,如果系统有一些的访问更新队列,你的代理方法locationManager:didReceiveUpdates:
将会调用多次,每次都只调用一个访问,而不是一个CLLocation
对象数组。调用manager.stopMonitoringVisits()
将会停止定位跟踪。
访问处理句柄
每个CLVisit
对象包含着一些基础属性:平均坐标,水平精度,以及数据到达与离开得时间戳。
每次访问被记录,CLLocationManagerDelegate
会被通知两次:一旦用户刚到达一个新地点,一个用户刚准备离开这个地点。你可以通过departureDate
属性计算出它们哪个是哪个;如果离开时间是NSDate.distantFuture()
意味着用户还在那儿。
func locationManager(manager: CLLocationManager!, didVisit visit: CLVisit!) {
if visit.departureDate.isEqualToDate(NSDate.distantFuture()) {
// User has arrived, but not left, the location
} else {
// The visit is complete
}
}
告警实现
略。。。。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。