iOS開發之定位

在iOS開發中,定位是不少App都須要使用的功能。本文主要對iOS中的定位知識點進行介紹。本文代碼環境爲:Xcode 10.1 + Swift 4.2bash

1、模塊與常見類

  • 定位所包含的類都在CoreLocation模塊中,因此必須導入import CoreLocation
  • CLLocation:表示某個位置的地理信息,好比經緯度、海拔等
  • CLLocationManager:定位管理器,能夠理解爲定位不能本身工做,須要有個管理者對它進行全過程監督。
  • CLGeocoder:地理編碼,分爲兩種
    • 正向地理編碼:根據位置信息,獲取具體的經緯度等信息
    • 反向地理編碼:根據給定的經緯度等信息,獲取位置信息
  • CLPlacemark:位置信息,包含的信息如國家、城市、街道等
  • CLLocationManagerDelegate:定位代理,不論是定位成功與失敗,都會有相應的代理方法回調
  • 具體的工做流程 (1)CLLocationManager發起定位,定位成功或者失敗都會回調CLLocationManagerDelegate中相應的代理方法 (2)在成功的代理方法中獲取 CLLocation 對象,進而獲取經緯度 (3)經過 CLGeocoder獲取經緯度對應的位置信息CLPlacemark (4)經過CLPlacemark獲取具體的位置信息

2、權限

在iOS中,隱私保護特別好,凡事須要定位的時候,第一次必須彈出對話框給用戶選擇,一共有兩種權限ide

  • 使用時才定位權限,使用這種,必須走兩步 (1)程序中發起 requestWhenInUseAuthorization (2)在info.plist對應的位置寫明申請權限的具體緣由
  • 一直能夠定位權限,使用這種,也是兩步 (1)程序中發起 requestAlwaysAuthorization (2)在info.plist對應的位置寫明申請權限的具體緣由
  • 配置字段說明
    • iOS 8以前只須要配置 Privacy - Location Usage Description
    • iOS 8 - iOS 10 只有兩個配置 Privacy - Location Always Usage Description Privacy - Location When In Use Usage Description
    • iOS 11以後多了Privacy - Location Always and When In Use Usage Description,因此iOS11以後必須配置的是 Privacy - Location When In Use Usage DescriptionPrivacy - Location Always and When In Use Usage Description
      權限緣由填寫

注意:上架的App這個緣由必須寫明確測試

3、模擬器定位

因爲定位須要GPS,因此通常狀況下,都須要真機進行測試,筆者在教學過程當中,常用的是一種模擬定位,這種定位須要準備一個gpx 的文件,能夠取名 XXX.gpx,裏面的內容以下:ui

<?xml version="1.0" encoding="UTF-8" ?>
<gpx version="1.1"
     creator="GMapToGPX 6.4j - http://www.elsewhere.org/GMapToGPX/"
     xmlns="http://www.topografix.com/GPX/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">
      <!--安徽商貿職業技術學院 谷歌地球:31.2906511800,118.3623587000-->
      <wpt lat="31.2906511800" lon="118.3623587000">
          <name>安徽商貿職業技術學院</name>
          <cmt>中國安徽省蕪湖市弋江區文昌西路24號 郵政編碼: 241002</cmt>
          <desc>中國安徽省蕪湖市弋江區文昌西路24號 郵政編碼: 241002</desc>
      </wpt>
</gpx>
複製代碼

將本身的定位信息填寫進xml對應的位置便可,而後選擇Edit Scheme,在Options中選擇本身的gpx 的文件,這樣模擬器運行的時候就會讀取該文件的位置信息。 編碼

Edit Scheme

4、後臺定位

若是你的App須要後臺定位,能夠這樣作,首先在Capabilities中打開後臺模式 spa

後臺模式
前面說過定位權限分兩種,針對這兩種狀況,後臺定位的代碼不同,效果也不同

  • 使用時才定位權限須要加上locationManager.allowsBackgroundLocationUpdates = true 開啓後臺定位,而一直能夠定位權限不須要寫任何額外代碼
  • 使用時才定位權限退出後,手機頂部會有藍條提示,而一直能夠定位權限則沒有

後臺定位藍條提醒

5、開發步驟與示例代碼

  1. 導入CoreLocation模塊
  2. 建立CLLcationManager對象,設置參數和代理,請求定位受權並配置info.plist
  3. 調用CLLcationManager對象的startUpdatingLocation方法進行定位
  4. 實現代理方法,在定位成功的方法中進行位置信息的處理
import UIKit
import CoreLocation

class ViewController: UIViewController {   
    //定位須要一個CLLocationManager
    lazy var locationManager:CLLocationManager = CLLocationManager()

    override func viewDidLoad() {
        super.viewDidLoad()
        setupManager()
    }

    func setupManager(){
        
        //默認狀況是這樣的,每當位置改變時LocationManager就調用一次代理。經過設置distanceFilter能夠實現當位置改變超出必定範圍時LocationManager才調用相應的代理方法。這樣能夠達到省電的目的。
        locationManager.distanceFilter = 300      
        //精度 好比爲10 就會盡可能達到10米之內的精度
        locationManager.desiredAccuracy = kCLLocationAccuracyBest 
        //代理
        locationManager.delegate = self 
        //第一種:能後臺定位可是會在頂部出現大藍條(打開後臺定位的開關)
        //容許後臺定位
        locationManager.allowsBackgroundLocationUpdates = true
        locationManager.requestWhenInUseAuthorization()   
        //第二種:能後臺定位而且不會出現大藍條
        //locationManager.requestAlwaysAuthorization()
        
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        
        //發起位置更新(定位)會一直輪詢,耗電
        self.locationManager.startUpdatingLocation()
    }
    
}


extension ViewController : CLLocationManagerDelegate{
    
    //定位成功
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        
        let location = locations.last      
        //地理編碼的類
        let gecoder = CLGeocoder()      
        if let location = location {
            //反地理編碼 轉換成 具體的地址
            gecoder.reverseGeocodeLocation(location) { (placeMarks, error) in            
                //CLPlacemark -- 國家 城市 街道
                let placeMark = placeMarks?.first        
                if let placeMark = placeMark{      
                    print("\(placeMark.country!) -- \(placeMark.name!) -- \(placeMark.locality!)")
                }       
            }
        }
        self.locationManager.stopUpdatingLocation()    
    }
    
    //定位失敗
    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        print(error)
        
    } 
}
複製代碼

6、代碼運行效果

運行效果
相關文章
相關標籤/搜索