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常用属性与方法
关于授权
-
使用期间授权:只有应用在前台(屏幕显示应用程序主界面)时,应用才开使用定位服务
// 对应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对象添加到视图当中
-
在地图上显示当前所在位置
-
获取授权并设置 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)
}