CoreLocation(定位與地理編碼等)
使用步驟:
- 導入CoreLocation庫
- 創建CLLocationManager對象
- 請求用戶授權 --- 需要在Info.plist中加入
NSLocationWhenInUseUsageDescription
這個鍵 - 設置代理 --- 並實現相應代理方法
- 調用開始定位方法
-
調用結束定位方法
import UIKit import CoreLocation class ViewController: UIViewController { // 1. 創建CLLocationManager對象 lazy var locationManger = CLLocationManager() override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. // 2. 請求用戶授權 locationManger.requestWhenInUseAuthorization() // 3. 設置代理 locationManger.delegate = self // 4. 調用開始定位方法 locationManger.startUpdatingLocation() } } // MARK: - 實現相應代理方法 extension ViewController: CLLocationManagerDelegate { func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { let lastLocation = locations.last! print(lastLocation) // 5. 調用結束定位方法 manager.stopUpdatingLocation() } }
持續定位優化(設置這些屬性可降低功耗)
-
設置距離篩選
// 距離篩選器,當位置發生至少10米的改變時纔會調用更新位置的代理方法 locationManger.distanceFilter = 10
-
設置定位精確度
// 定位的精準度 /* * kCLLocationAccuracyBestForNavigation 精準度儘可能高(導航時使用) * kCLLocationAccuracyBest 精準度儘可能高 * kCLLocationAccuracyNearestTenMeters 10米以內誤差 * kCLLocationAccuracyHundredMeters 百米誤差 * kCLLocationAccuracyKilometer 千米誤差 * kCLLocationAccuracyThreeKilometers 三千米誤差 */ locationManger.desiredAccuracy = kCLLocationAccuracyBest
CLLocation常用屬性與方法
-
經緯度
let location = lastLocation let coordinate = location.coordinate // 維度 print(coordinate.latitude) // 經度 print(coordinate.longitude)
-
兩個位置之間的距離(直線距離)
let distance = location.distance(from: location2)
關於授權
-
使用期間授權:只有應用在前臺(屏幕顯示應用程序主界面)時,應用纔開使用定位服務
// 對應Info.plist中的 NSLocationWhenInUseUsageDescription,描述爲何使用定位服務 locationManger.requestWhenInUseAuthorization()
-
始終授權:即使應用在後臺,應用也可以使用定位服務
// 對應Info.plist中的 NSLocationAlwaysAndWhenInUseUsageDescription locationManger.requestAlwaysAuthorization()
CLGeocoder(地理編碼)
-
地理編碼(使用地名獲取地理信息)
CLGeocoder().geocodeAddressString("上海市") { (placemarks, error) in // 使用前需要判斷下placemarks, error // 需要注意重名問題 print(placemarks) }
-
反地理編碼(使用經緯度獲取位置信息)
CLGeocoder().reverseGeocodeLocation(CLLocation(latitude: 31.23727100, longitude: 121.45111100)) { (placemarks, error) in // 使用前需要判斷下placemarks, error print(placemarks) }
- 注意:placemarks是[CLPlacemark]類型,可以通過其屬性獲取詳細地址,街道地址,城市名等位置信息
MapKit
MapView
-
使用:
- 導入MapKit框架
import MapKit
- 對於storyboard或xib從控件庫中拖拽一個map kit view到一個view上;或者使用代碼創建一個MKMapView對象添加到視圖當中
- 導入MapKit框架
-
在地圖上顯示當前所在位置
-
獲取授權並設置
userTrackingMode
屬性var locationManager = CLLocationManager() locationManager.requestWhenInUseAuthorization() // 要使用代理方法就設置,否則不用設置 mapView.delegate = self // case none = 0 // the user's location is not followed // case follow = 1 // the map follows the user's location 顯示位置 // case followWithHeading = 2 // the map follows the user's location and heading 顯示位置和方向 mapView.userTrackingMode = .follow
-
使用代理可獲取最新位置的詳細信息
extension MapController: MKMapViewDelegate { func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation) { print(userLocation.location) // 可在此設置用戶所在位置大頭針的信息 //CLGeocoder().reverseGeocodeLocation(userLocation.location!) { (placemarks, error) in // let placemark = placemarks?.last // 被點擊後彈出氣泡的標題與子標題 // userLocation.title = placemark?.locality // userLocation.subtitle = placemark?.name //} } }
-
-
設置地圖類型
// A street map that shows the position of all roads and some road names. // case standard = 0 // 標準地圖,有街道信息等 // Satellite imagery of the area. // case satellite = 1 // 衛星圖 // A satellite image of the area with road and road name information layered on top. // case hybrid = 2 // 衛星圖並顯示街道信息 /* 這幾種暫時在中國區沒啥用 // @available(iOS 9.0, *) // case satelliteFlyover = 3 // @available(iOS 9.0, *) // case hybridFlyover = 4 // @available(iOS 11.0, *) // case mutedStandard = 5 */ mapView.mapType = .standard
-
設置地圖中心點座標或顯示區域
// 設置地圖所顯示的中心點 // mapView.centerCoordinate = userLocation.location!.coordinate // 設置地圖所顯示的中心點和所顯示的區域 // mapView.region = MKCoordinateRegion(center: userLocation.location!.coordinate, span: MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)) // 設置地圖所顯示的中心點和所顯示的區域(當從另一區域變化到所設置的區域時有動畫) // 可調用此屬性進行地圖的放大與縮小 mapView.setRegion(MKCoordinateRegion(center: userLocation.location!.coordinate, span: MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)), animated: true)
-
額外信息或控件的顯示與隱藏
-
指北針
// 顯示指北針 默認就是true,當用戶旋轉地圖時顯示,點擊回到初始方向 mapView.showsCompass = true
-
交通狀況
// 顯示交通狀況 mapView.showsTraffic = true
-
比例尺
// 顯示比例尺 mapView.showsScale = true
-
大頭針
- 基本使用
- 自定義大頭針數據模型類(需遵守MKAnnotation協議)
- 創建大頭針對象
-
將大頭針添加到地圖上
// 1. 自定義大頭針數據模型類 class MyAnnotation: NSObject, MKAnnotation { var coordinate: CLLocationCoordinate2D var title: String? var subtitle: String? init(coordinate: CLLocationCoordinate2D, title: String?, subtitle: String?) { self.coordinate = coordinate self.title = title self.subtitle = subtitle } } // 寫在存在MapView的視圖控制器的方法中 // 2. 創建大頭針對象 let annotiton1 = MyAnnotation(coordinate: CLLocationCoordinate2D(latitude: 39.90680600, longitude: 116.39877350), title: "北京", subtitle: "中國北京") // 2. 創建大頭針對象 let annotiton2 = MyAnnotation(coordinate: CLLocationCoordinate2D(latitude: 31.23170600, longitude: 121.47264400), title: "上海", subtitle: "中國上海") // 3. 將大頭針添加到地圖上 mapView.addAnnotations([annotiton1, annotiton2])
-
自定義大頭針視圖(實現下面的代理方法)
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? { // 如果是用戶位置的大頭針視圖直接返回nil,否則會將其也變爲自定義大頭針視圖 guard !(annotation is MKUserLocation) else { return nil } // 1. 從緩存池中獲取可重用的大頭針視圖 需自己實現 MyAnnotationView 的定義 let view = mapView.dequeueReusableAnnotationView( withIdentifier: "MyAnnotationView") as? MyAnnotationView annotationView = view ?? MyAnnotationView(annotation: annotation, reuseIdentifier: "MyAnnotationView") // 2. 設置MyAnnotationView需要設置的屬性 …… // 返回自定義大頭針視圖 return annotationView }
地圖上畫線
- 創建起點MKMapItem
- 創建終點MKMapItem
- 創建方向請求並設置起點終點
- 根據請求創建MKDirections對象
- 計算路線
- 添加路線到地圖視圖上
- 實現代理方法
let direction = "上海"
CLGeocoder().geocodeAddressString(direction!) { (placemarks, error) in
// 1. 創建起點MKMapItem
let sourceItem = MKMapItem.forCurrentLocation()
// 2. 創建終點MKMapItem
let destinationItem = MKMapItem(placemark: MKPlacemark(placemark: placemarks!.last!))
// 3. 創建方向請求並設置起點終點
let request = MKDirections.Request()
request.source = sourceItem
request.destination = destinationItem
request.transportType = .automobile
// 4. 根據請求創建MKDirections對象
let directions = MKDirections(request: request)
// 5. 計算路線
directions.calculate { (response, error) in
guard let response = response else {
if let error = error {
print("Error: \(error)")
}
return
}
response.routes.forEach({ (route) in
// 6. 添加路線到地圖視圖上
let polyine = route.polyline
self.mapView.addOverlay(polyine, level: .aboveRoads)
})
}
}
// 7. 實現代理方法
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let renderer = MKPolygonRenderer(overlay: overlay)
// 設置線的顏色
renderer.strokeColor = .blue
// 設置線寬
renderer.lineWidth = 5
return renderer
}
導航(跳轉到系統地圖)
- 使用導航目的地創建一個MKMapItem
- 構建打開系統地圖時的選項(如導航模式、地圖類型等)
- 調用openMaps方法打開系統地圖
// 0. 導航目的地
let destination = "上海"
CLGeocoder().geocodeAddressString(direction!) { (placemarks, error) in
// 1. 使用導航目的地創建一個MKMapItem
let destinationItem = MKMapItem(placemark: MKPlacemark(placemark: placemarks!.last!))
// 2. 構建打開系統地圖時的選項(如導航模式、地圖類型等)
let options = [MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving,
MKLaunchOptionsMapTypeKey: 0,
MKLaunchOptionsShowsTrafficKey: true] as [String : Any]
// 3. 調用openMaps方法打開系統地圖
MKMapItem.openMaps(with: [destinationItem], launchOptions: options)
}