iOS開發(fā)之定位

在iOS開發(fā)中,定位是很多App都需要使用的功能。本文主要對(duì)iOS中的定位知識(shí)點(diǎn)進(jìn)行介紹。本文代碼環(huán)境為:Xcode 10.1 + Swift 4.2。

一、模塊與常見類

  • 定位所包含的類都在CoreLocation模塊中,所以必須導(dǎo)入import CoreLocation
  • CLLocation:表示某個(gè)位置的地理信息,比如經(jīng)緯度、海拔等
  • CLLocationManager:定位管理器,可以理解為定位不能自己工作,需要有個(gè)管理者對(duì)它進(jìn)行全過(guò)程監(jiān)督。
  • CLGeocoder:地理編碼,分為兩種
    • 正向地理編碼:根據(jù)位置信息,獲取具體的經(jīng)緯度等信息
    • 反向地理編碼:根據(jù)給定的經(jīng)緯度等信息,獲取位置信息
  • CLPlacemark:位置信息,包含的信息如國(guó)家、城市、街道等
  • CLLocationManagerDelegate:定位代理,不管是定位成功與失敗,都會(huì)有相應(yīng)的代理方法回調(diào)
  • 具體的工作流程
    (1)CLLocationManager發(fā)起定位,定位成功或者失敗都會(huì)回調(diào)CLLocationManagerDelegate中相應(yīng)的代理方法
    (2)在成功的代理方法中獲取 CLLocation 對(duì)象,進(jìn)而獲取經(jīng)緯度
    (3)通過(guò) CLGeocoder獲取經(jīng)緯度對(duì)應(yīng)的位置信息CLPlacemark
    (4)通過(guò)CLPlacemark獲取具體的位置信息

二、權(quán)限

在iOS中,隱私保護(hù)特別好,凡事需要定位的時(shí)候,第一次必須彈出對(duì)話框給用戶選擇,一共有兩種權(quán)限

  • 使用時(shí)才定位權(quán)限,使用這種,必須走兩步
    (1)程序中發(fā)起 requestWhenInUseAuthorization
    (2)在info.plist對(duì)應(yīng)的位置寫明申請(qǐng)權(quán)限的具體原因
  • 一直可以定位權(quán)限,使用這種,也是兩步
    (1)程序中發(fā)起 requestAlwaysAuthorization
    (2)在info.plist對(duì)應(yīng)的位置寫明申請(qǐng)權(quán)限的具體原因
  • 配置字段說(shuō)明
    • iOS 8之前只需要配置
      Privacy - Location Usage Description
    • iOS 8 - iOS 10 只有兩個(gè)配置
      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
      權(quán)限原因填寫

注意:上架的App這個(gè)原因必須寫明確

三、模擬器定位

由于定位需要GPS,所以一般情況下,都需要真機(jī)進(jìn)行測(cè)試,筆者在教學(xué)過(guò)程中,經(jīng)常使用的是一種模擬定位,這種定位需要準(zhǔn)備一個(gè)gpx 的文件,可以取名 XXX.gpx,里面的內(nèi)容如下:

<?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">
      <!--安徽商貿(mào)職業(yè)技術(shù)學(xué)院 谷歌地球:31.2906511800,118.3623587000-->
      <wpt lat="31.2906511800" lon="118.3623587000">
          <name>安徽商貿(mào)職業(yè)技術(shù)學(xué)院</name>
          <cmt>中國(guó)安徽省蕪湖市弋江區(qū)文昌西路24號(hào) 郵政編碼: 241002</cmt>
          <desc>中國(guó)安徽省蕪湖市弋江區(qū)文昌西路24號(hào) 郵政編碼: 241002</desc>
      </wpt>
</gpx>

將自己的定位信息填寫進(jìn)xml對(duì)應(yīng)的位置即可,然后選擇Edit Scheme,在Options中選擇自己的gpx 的文件,這樣模擬器運(yùn)行的時(shí)候就會(huì)讀取該文件的位置信息。

Edit Scheme

四、后臺(tái)定位

如果你的App需要后臺(tái)定位,可以這樣做,首先在Capabilities中打開后臺(tái)模式

后臺(tái)模式

前面說(shuō)過(guò)定位權(quán)限分兩種,針對(duì)這兩種情況,后臺(tái)定位的代碼不一樣,效果也不一樣

  • 使用時(shí)才定位權(quán)限需要加上locationManager.allowsBackgroundLocationUpdates = true
    開啟后臺(tái)定位,而一直可以定位權(quán)限不需要寫任何額外代碼
  • 使用時(shí)才定位權(quán)限退出后,手機(jī)頂部會(huì)有藍(lán)條提示,而一直可以定位權(quán)限則沒(méi)有
后臺(tái)定位藍(lán)條提醒

五、開發(fā)步驟與示例代碼

  1. 導(dǎo)入CoreLocation模塊
  2. 創(chuàng)建CLLcationManager對(duì)象,設(shè)置參數(shù)和代理,請(qǐng)求定位授權(quán)并配置info.plist
  3. 調(diào)用CLLcationManager對(duì)象的startUpdatingLocation方法進(jìn)行定位
  4. 實(shí)現(xiàn)代理方法,在定位成功的方法中進(jìn)行位置信息的處理
import UIKit
import CoreLocation

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

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

    func setupManager(){
        
        //默認(rèn)情況是這樣的,每當(dāng)位置改變時(shí)LocationManager就調(diào)用一次代理。通過(guò)設(shè)置distanceFilter可以實(shí)現(xiàn)當(dāng)位置改變超出一定范圍時(shí)LocationManager才調(diào)用相應(yīng)的代理方法。這樣可以達(dá)到省電的目的。
        locationManager.distanceFilter = 300      
        //精度 比如為10 就會(huì)盡量達(dá)到10米以內(nèi)的精度
        locationManager.desiredAccuracy = kCLLocationAccuracyBest 
        //代理
        locationManager.delegate = self 
        //第一種:能后臺(tái)定位但是會(huì)在頂部出現(xiàn)大藍(lán)條(打開后臺(tái)定位的開關(guān))
        //允許后臺(tái)定位
        locationManager.allowsBackgroundLocationUpdates = true
        locationManager.requestWhenInUseAuthorization()   
        //第二種:能后臺(tái)定位并且不會(huì)出現(xiàn)大藍(lán)條
        //locationManager.requestAlwaysAuthorization()
        
    }

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


extension ViewController : CLLocationManagerDelegate{
    
    //定位成功
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        
        let location = locations.last      
        //地理編碼的類
        let gecoder = CLGeocoder()      
        if let location = location {
            //反地理編碼 轉(zhuǎn)換成 具體的地址
            gecoder.reverseGeocodeLocation(location) { (placeMarks, error) in            
                //CLPlacemark -- 國(guó)家 城市 街道
                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)
        
    } 
}

六、代碼運(yùn)行效果

運(yùn)行效果
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容