iOS8 Core Location

前言

當腎Phone出現,定位服務一直都是做爲一個前沿技術跟中心存在。CL API在腎平臺SDK第一次發佈的時候就列入了公開接口。在每次新發布的iOS版本中,大蘋果老是按部就班的增長一些新功能到CL框架,好比後臺定位,geocoding亦或是iBeacons。數組

iOS8義無反顧往前走。更其餘領域的最新更新同樣,CL已經動搖了,隨着新設計容許讓開發去建立以前他們沒法完成的新東西的同時還幫助保護用戶隱私。特別的,iOS8爲CL框架帶了3套主要的改變:更粗糙的受權,室內定位,還有訪問監控。網絡

受權

APP有多種緣由像你獲取地址信息受權。(此處省略各類緣由舉栗子)app

iOS8之前,定位服務受權是二進制的:給或者不給。設置的應用選項會展現那些是你受權後臺定位服務的APP,可是你除了徹底受權使用定位服務外不能再作其餘處理了(短暫使用)。框架

iOS8對這方面作了修正,有如下兩種受權方式。異步

  • 在APP在使用的時候受權
  • 一直受權

這毫無疑問對用戶隱私來講是一個利好,可是對於開發來講呵呵。。工具

請求受權

在早先的iOS,定位服務的受權請求是很隱式的。建立一個CLLocationManager實例,若是用戶尚未顯示的贊成或者拒絕一個APP的定位服務受權下面得代碼會在觸發探測用戶受權定位服務。this

import Foundation
import CoreLocation

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

爲了讓事情簡單點,假設上述代碼中咱們已經聲明瞭manager實例做爲成員變量,而且也設置了它的代理。url

每次讓CLLocationManager獲取最新地址信息的動做都會彈出定位服務受權框。spa

在iOS8,請求受權與開始使用定位服務是兩個不一樣的動做。特別地,這裏有兩個不一樣的方法你能夠用來顯式的請求受權requestWhenInUseAuthorizationrequestAlwaysAuthorization。前者只是容許你在應用打開得時候獲取地位位置信息。後者則容許一直在後臺獲取地理位置信息。操作系統

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

告警實現

略。。。。

相關文章
相關標籤/搜索