文档章节

Core Location in i​OS 8

nerozhao
 nerozhao
发布于 2015/05/29 07:07
字数 2957
阅读 67
收藏 1
点赞 0
评论 0

自从 iPhone 存在以来,位置服务就一直处于非常重要的位置。Maps.app 是第一代 iPhone 里杀手锏的功能之一。Core Location API 也在 iPhone OS SDK 最初的公开版本里就存在了。每一次发布 iOS,Apple 都会给这个库逐步添加新功能,比如后台运行的位置服务,坐标化,以及室内定位( iBeacons )。

iOS 8 仍然继续坚定的延续着这个进程。跟其他最新的更新类似,Core Location 被改动了不少,不管是允许开发者做之前并不被允许的开发,还是帮助维护用户隐私。更特别的是,iOS 8 给 Core Location 带来了三个主要的改进:更分化的权限,室内定位以及访问监控。

权限

一个 app 总有各种各样的理由需要得到你的位置信息。一个能够提示你每个转弯在哪里的 GPS 应用就需要持续获得你的位置信息,才可以在转弯的时候提示你。一个餐厅推荐的 app 也需要得到你的位置信息(即便它并没有打开的情况下),才可以在你到你朋友点赞的餐厅附近的时候能收到推送消息。一个 Twitter 应用在发推的时候也可能需要你的位置,但在你不使用的时候不应该监控你的位置。

在 iOS 8 之前,位置服务的权限是二元的:你要么赋予一个应用得到使用位置服务的权限,要么不给。你可以在 Settings.app 查看哪些 app 可以在后台取得你的位置信息,但除了完全不让这个 app 使用位置服务之外,你不能做任何的事来阻止它获取位置信息。

iOS 8 修改了这个问题,它把位置服务权限拆分成了 2 个不同的授权。

  • “使用期间” 的授权会只允许应用在 - 就跟你猜测的一样 - 使用期间取得你的位置信息。

  • “始终” 的授权则跟之前版本的 iOS 那样,会给应用后台权限。

这是对用户隐私的一个重大改进,但对于我们开发者来说则意味着多一些的工作。

取得权限

在早前的 iOS 版本中,获取位置服务权限是隐式的。比如 CLLocationManager,如果应用程序还没有被许可或者之前被拒绝了的话,下面的代码会触发系统弹出提示框向用户获取位置服务的授权:

Swift

import Foundation import CoreLocation let manager = CLLocationManager() if CLLocationManager.locationServicesEnabled() {     manager.startUpdatingLocation() }

把事情简化一下,假定我们声明了一个 manager 实例作为所有例子的成员变量,它的 delegate 是它的 owner。

让 CLLocationManager 取得最新的位置的这个操作会让系统弹出是否允许位置服务的提示。

在 iOS 8,取得权限和使用位置服务已经分成两个动作了。分别用两个不同的方法取得权限:requestWhenInUseAuthorization 和 requestAlwaysAuthorization。前者只能让应用在使用的时候有权获取位置数据;后者会得到跟之前 iOS 一样的后台位置服务。

Swift

if CLLocationManager.authorizationStatus() == .NotDetermined {     manager.requestAlwaysAuthorization() }

或者

Swift

if CLLocationManager.authorizationStatus() == .NotDetermined {     manager.requestWhenInUseAuthorization() }

因为这是异步的,应用不能立即开始使用位置服务。取而代之的是,应用必须实现 locationManager:didChangeAuthorizationStatus 的 delegate 方法,这个方法会在用户改变权限状态的时候调用。

如果用户之前已经授权了位置服务,那么在每次位置管理器被初始化,并且 delegate 被设置了相应的权限状态的情况下这个代理方法仍然会被调用。这使得一个单一的代码路径使用定位服务更为方便。

Swift

func locationManager(manager: CLLocationManager!,                      didChangeAuthorizationStatus status: CLAuthorizationStatus) {     if status == .AuthorizedAlways || status == .AuthorizedWhenInUse {         manager.startUpdatingLocation()         // ...     } }

描述字符串

想在 iOS 8 中使用定位,另一个改变是必须的。在这之前,应用可以选择性的在 Info.plist 中包含 'NSLocationUsageDescription' 的关键字。这个值是一个纯文本的字符串,向用户说明了应用预期要使用位置服务。现在这个值被拆分成了两个不同的关键字(NSLocationWhenInUseUsageDescription 和 NSLocationAlwaysUsageDescription),而且是必填的;如果你不添加对应的关键字就去调用 requestWhenInUseAuthorization 或 requestAlwaysAuthorization,那么将不会有任何的弹出提示给用户。

Core Location Always Authorization

Core Location When In Use Authorization

获取多个权限

另一个值得注意的细节是授权的弹出框会只显示一次。在 CLLocationManager.authorizationStatus() 返回除 NotDetermined 之外的值之后,不管调用 requestWhenInUseAuthorization() 或 requestAlwaysAuthorization() 都不会有一个 UIAlertController 显示出来了。在用户最初的选择之后,唯一改变授权的方式是到 Settings.app 或者到隐私设置,又或者是应用自己的设置页面。

旧的授权机制各种不方便的情况下,现在让应用在它的生存周期内询问不论是“使用期间”还是“始终”的权限的机制明显复杂多了,更不方便了。为了缓解这一点,Apple 引入了一个字符串常量,UIApplicationOpenSettingsURLString,它存储了一个 URL 用来打开当前应用在 Settings.app 对应的页面。

下面的例子显示了如何在应用里弹出两种类型的权限获取窗口,如果你的应用打算获取始终的权限的话,可以参考一下。

Swift

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) }

Core Location Settings Alert

Core Location Settings Location Never

Core Location Settings Location Always

向后兼容

所有这些新的 API 都只支持 iOS 8。对于要支持 iOS 7 或之前 iOS 版本的应用,则必须维护两部分代码,一个是为 iOS 8 获取权限的,同时还需要维护之前的获取位置更新的方法。一个简单的实现会看上去像下面这样:

Swift

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()     } }

建立用户的信任

现在在 iOS 8 上有一个共同的变化趋势是:它们更容易得到用户的信任。

显式的请求的授权,鼓励应用程序在用户试图做一些事情之前不请求授权。这包括了用使用说明来很清晰的解释为什么你需要的访问位置信息,以及应用程序将如何使用它。“使用期间” 和 “始终” 的区别授权,使用户感到轻松,因为应用只得到了需要的数据。

当然,这些新的 API 并不能阻止应用做跟之前一样的事。所有应用 “需要” 针对支持 iOS 8 的事只是添加对 useAlwaysAuthorization 的调用,以及添加一个全局适用的字符串。但随着这些新的变化, Apple 正在传达一个重要的信息,那就是你应该尊重你的用户。一旦用户习惯了像这样尊重用户隐私的应用程序,不难想象的是,不负责任地使用定位服务 的应用会在 App Store 得到更多负面的评分。

室内定位追踪

如果一个人仔细阅读了 CoreLocation.framework 的 API 改动文件,会发现最令人费解的改动之一是引进了 CLFloor,一个新的只有相当简单的接口对象:

SwiftObjective-C

class CLFloor : NSObject {     var level: Int { get } }

就是这样。仅一个属性,一个整形值来表示当前位置处于建筑物的第几层楼。

欧洲人肯定会很高兴的发现一楼是用 '1' 表示的, 而不是 '0'。

由 CLLocationManager 返回的 CLLocation 对象可能包括一个 floor 属性,但如果你是写一个使用定位服务的示例应用程序,你会发现 CLLocation 对象的 floor 属性总是 nil

这是因为该API的变化只是 iOS8 中引入的室内定位跟踪这个大功能的冰山一角。对于大型空间的应用开发,例如艺术博物馆或百货公司这种, Apple 现在已经有结合了无线,GPS,蜂窝,和 室内定位数据的内置 Core Location API 支持 IPS 。

也就是说,这个新功能的信息令人吃惊的来之不易。该项目目前被很好的严格限制访问了,仅允许已通过从 Apple Maps Connect 申请的程序。关于该项目的的有限信息是在今年的WWDC(Session 708: Taking Core Location Indoors)被初露头角的,但大部分的后台细节都被隐藏在被关上的门之后了。对于大多数的我们来说,别无选择的,只能打消没有用的好奇心。

CLVisit

很多应用程序,使用位置监控的原因是确定用户是否在某个确定的地方。概念上讲,你在想的是诸如“地方”或“访问”的名词术语,而不是原始的 GPS 坐标。

然而,除非你可以得益于使用区域监视(被限制在一个相对小的数量的区域)或室内定位( iBeacon )测距(这要求把室内定位硬件真正安装在一个空间内),否则用 Core Location 的后台监控工具并不是非常适合。开发一个登记应用或像 Moves 这样的全面的日志应用,位置监控和花费很多时间做特定处理一般意味着消耗大量的电量。

在 iOS 8 里, Apple 曾试图通过引进 CLVisit 来解决这个问题, 这是一种新型的后台位置的监控。一个 CLVisit 表示该用户已经处于某个位置的时间长度,包括一个坐标和开始/结束的时间戳。

理论上讲,使用访问监控并不比任何其他后台定位跟踪做更多的事。简单地调用 manager.startMonitoringVisits() 将启用后台访问跟踪,假设用户同意授权你的应用程序“始终”的使用权限。一旦启动,你的应用程序将在有位置更新的时候在后台被唤醒,不像基本的定位监控,如果系统有个访问更新的队列(通常可以使更新延迟),你的 delegate 方法将被调用多次,每个单一的访问调用一次,而不是一个包含 CLLocation 对象的数组调用 locationManager:didReceiveUpdates:。调用 manager.stopMonitoringVisits() 会停止跟踪。

处理访问

每个 CLVisit 对象包含了一些基本属性:平均坐标,水平精度和到达日期和离开时间。

每次一个访问被追踪到,CLLocationManagerDelegate 可能会被告知两次:一次是在用户刚抵达一个新的地方的时候,以及当用户离开的时候。你可以通过检查 departureDate 属性来分辨它们; NSDate.distantFuture() 的离开时间意味着用户还在那儿。

Swift

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     } }

实现须知

至少到 iOS 8.1,CLVisit 还不是那么精确。开始和结束时间一般有一两分钟的误差,是否访问某个地方的线路边际有点模糊。在咖啡店的角落躲一分钟可能不会触发访问,但在等一个特别长的红绿灯的时候却有可能触发。很可能 Apple 将在操作系统的后续升级的时候提升访问检测的质量,但现在如果你的应用程序对访问检测的精度要求很高的话,你最好不要依赖 CLVisit


本文转载自:http://nshipster.cn/core-location-in-ios-8/

共有 人打赏支持
nerozhao
粉丝 10
博文 30
码字总数 5823
作品 0
武汉
程序员
servlet下载,使用迅雷时报错

使用ie,火狐的内置下载能够正常使用,但是一旦用迅雷就报错,有时候虽然报错,但偶尔又能把它下下来,只不过要阻塞很久。 代码如下: resp.setContentType("text/html; charset=UTF-8"); S...

藏剑
2014/10/13
407
1
Azure PowerShell 创建DS系列虚拟机

本部分介绍Azure PowerShell 创建DS系列虚拟机 启动 PowerShell 控制台,连接到订阅,并在控制台窗口中运行以下 PowerShell cmdlet $storageAccount = "hcjpremiumtest" $adminName = "huang...

huangbowen2005
2016/12/30
0
0
IOS8 里面 js如果调用本地app window.location.href 无法打开

if (navigator.userAgent.match(/(iPhone);?/i)) { var loadDateTime = new Date(); window.setTimeout(function() { var timeOutDateTime = new Date(); if (timeOutDateTime - loadDateTim......

shengcheng
2015/09/17
4.3K
1
Obtaining NumPy & SciPy libraries

Obtaining NumPy & SciPy libraries See also Installing the SciPy Stack Official Source and Binary Releases For each official release of NumPy and SciPy, we provide source code (t......

openthings
2015/12/29
60
0
Zorin OS 8 RC 发布,针对新手的 Linux 系统

Zorin OS 8 RC 发布,此版本是下一代 Zorin OS 的提前发布版,Zorin OS 8 改善了用户界面,更新了主题,添加了全新的软件,包括简单又漂亮的音乐播放器,Empathy 即时通讯客户端等。 更多信息...

oschina
2014/01/03
2.8K
3
Mac OS X: DeployStudio更新v1.0rc16

Mac OS X: DeployStudio更新v1.0rc16 更新信息DeplyStudio的最新更新v1.0rc16已经可以下载了,下载方法可以使用后面的shell命令。 更新: Admin: 可以定义使用AD的用户/用户组来认证用户. 程...

junwong
2012/03/09
0
0
Zorin OS 8 发布,针对新手的 Linux 系统

Zorin OS 8 发布,此版本更新内容请看 release announcement 。 Download (MD5): zorin-os-8-core-64.iso (1,658MB). Zorin OS是基于Ubuntu的Linux发行,特别为Linux新手而设计。它拥有类似W...

oschina
2014/01/29
3.4K
9
Eclipse---Refreshing /.org.eclipse.jdt.core.exter

有俩月了 eclipse一直在启动的时候提示Refreshing /.org.eclipse.jdt.core.external.folders/.link0,然后大概等5分钟才敢动它,否则就会假死 今天实在是受不了了 查了一下原因,最终在国外友...

SuShine
2015/10/09
249
0
nginx+django+gunicorn+gevent+supervisor

安装环境介绍: python2.7.10 django1.7.9 linux CentOS release 6.5 (Final) 64 假设我的项目位置为/var/www/myweb 服务器IP为192.168.0.100 1、插件安装 gunicorn-19.7.1 uwsgi组件 gevent......

withyx
2017/07/11
0
0
解决kvm安装windows7虚拟机cpu只有两个的问题

问题描述:使用下面的命令创建的虚拟机 virt-install --ram=2048 --vcpus=8 --os-type windows --os-variant=winvista --cdrom /ISOs/Windows7CHSsp1x86.iso --network bridge=br1 --disk pa......

鹏爱
2017/07/06
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

spring boot中swagger2使用

1.pom.xml中添加 <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version>......

说回答
3分钟前
0
0
tomcat虚拟路径的几种配置方法

tomcat虚拟路径的几种配置方法 一般我们都是直接引用webapps下面的web项目,如果我们要部署一个在其它地方的WEB项目,这就要在TOMCAT中设置虚拟路径了,Tomcat的加载web顺序是先加载 $Tomcat_ho...

Helios51
15分钟前
1
0
Mac 安装jupyter notebook的过程

MAC台式机 python:mac下自带Python 2.7.10 1.先升级了pip安装工具:sudo python -m pip install --upgrade --force pip 2.安装setuptools 工具:sudo pip install setuptools==33.1.1 3.安装......

火力全開
20分钟前
0
0
导航守卫解释与例子

“导航”表示路由正在发生改变。 正如其名,vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的。 记住...

tianyawhl
20分钟前
0
0
Java日志框架-logback配置文件多环境日志配置(开发、测试、生产)(原始解决方法)

说明:这种方式应该算是最通用的,原理是通过判断标签实现。 <!-- if-then form --> <if condition="some conditional expression"> <then> ... </then> </if> ......

浮躁的码农
35分钟前
1
0
FTP传输时的两种登录方式和区别

登录方式 匿名登录 用户名为: anonymous。 密码为:任何合法 email 地址。 授权登录 用户名为:用户在远程系统中的用户帐号。 密码为:用户在远程系统中的用户密码。 区别 匿名登录 只能访问...

寰宇01
36分钟前
0
0
plsql developer 配置监听(不安装oracle客户端)

plsql developer 配置监听(不安装oracle客户端)

微小宝
43分钟前
1
0
数据库(分库分表)中间件对比

本人的宗旨就是,能copy的,绝对不手写。 分区:对业务透明,分区只不过把存放数据的文件分成了许多小块,例如mysql中的一张表对应三个文件.MYD,MYI,frm。 根据一定的规则把数据文件(MYD)和索...

奔跑吧代码
47分钟前
2
0
Netty与Reactor模式详解

在学习Reactor模式之前,我们需要对“I/O的四种模型”以及“什么是I/O多路复用”进行简单的介绍,因为Reactor是一个使用了同步非阻塞的I/O多路复用机制的模式。 I/O的四种模型 I/0 操作 主要...

hutaishi
53分钟前
1
0
【2018.07.16学习笔记】【linux高级知识 20.16-20.19】

20.16/20.17 shell中的函数 20.18 shell中的数组 20.19 告警系统需求分析

lgsxp
58分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部