初识iOS 定位
2022-05-05 本文已影响0人
gale_小米
- CClocationManager 用于启动和停止向应用程序传递位置相关事件的对象。
- CCLocation 表示地理坐标以及精度和时间戳信息。
override func viewDidLoad() {
super.viewDidLoad()
if CLLocationManager.locationServicesEnabled() { //判断设备是否支持定位服务
self.loationManager = CLLocationManager()
//设置定位到精确度
self.loationManager?.desiredAccuracy = kCLLocationAccuracyBest
self.loationManager?.distanceFilter = 50 //设置定位距离
if #available(iOS 8.0, *){
print("\(UIDevice.current.systemVersion)")
//self.loationManager?.requestWhenInUseAuthorization() // 设置启用时间
self.loationManager?.requestAlwaysAuthorization() //一直启用
}
self.loationManager?.delegate = self
self.loationManager?.startUpdatingLocation() //开启定位
}
}
//定位失败
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("locationManager =\(error.localizedDescription)")
}
//定位成功
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if locations.count > 0 {
//获取最新的定位信息
let locationInfo:CLLocation = locations.last! as CLLocation
let alertView = UIAlertController(title: "定位成功", message: "当前位置\(locationInfo.coordinate.longitude),\(locationInfo.coordinate.latitude)", preferredStyle: UIAlertController.Style.alert)
alertView.addAction(UIAlertAction(title: "确定", style: UIAlertAction.Style.cancel, handler: { alertView in
self.dismiss(animated: true, completion: nil)
}))
self.present(alertView, animated: true, completion: nil)
}
}
3.CLPlacemark 表示地理位置的位置标记数据。地名数据可以是国家、州、城市和街道地址等信息。
4.CLGeocoder 用于在地理坐标和地名之间转换的接口。
//解析地理位置
let gl:CLGeocoder = CLGeocoder()
//根据经纬度编码当前位置信息
gl.reverseGeocodeLocation(locationInfo) { (array : [CLPlacemark]!, err : Error!) in
if array.count > 0 {
//这里可能会存在多个位置需要根据实际需求选择
let placmark:CLPlacemark = array.last! as CLPlacemark
//print("placmarks = \(placmark.location) ,\(placmark.region)")
let alertView = UIAlertController(title: "定位成功", message: "当前位置\(placmark.country!.description),\(placmark.administrativeArea!.description),\(placmark.locality!.description),\(placmark.thoroughfare!.description),\(placmark.timeZone!.description)", preferredStyle: UIAlertController.Style.alert)
alertView.addAction(UIAlertAction(title: "确定", style: UIAlertAction.Style.cancel, handler: { alertView in
self.dismiss(animated: true, completion: nil)
}))
self.present(alertView, animated: true, completion: nil)
}
}
5.添加锚点,区域,水印
/*设置精确位置*/
func locationLatitudeAndLongitude(latitude:Double ,longitude:Double){
let coordinate2d:CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
//设置一个精确范围,值越小精确度越高
let span :MKCoordinateSpan = MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta:0.01)
let region:MKCoordinateRegion = MKCoordinateRegion(center: coordinate2d, span: span)
//定位到点
self.mapView?.setRegion(region, animated: true)
//定位大致区域
// let mapRect:MKMapRect = MKMapRect(origin: MKMapPoint(coordinate2d), size: MKMapSize(width: 1000.0, height: 1000.0))
// self.mapView?.setVisibleMapRect(mapRect, animated: true)
//添加锚点
// let annotaion:MKPointAnnotation = MKPointAnnotation()
// annotaion.coordinate = coordinate2d
// annotaion.title = "我在这"
// annotaion.subtitle = "i am gale"
// self.mapView?.addAnnotation(annotaion)
}
@objc func mapViewTap(gesture:UILongPressGestureRecognizer){
if gesture.state == .began {
//获取屏幕的物理坐标
let point:CGPoint = gesture.location(in: self.mapView)
//把物理坐标点转换为coor
let coor:CLLocationCoordinate2D = self.mapView!.convert(point, toCoordinateFrom: self.mapView)
//定义一个覆盖层
let overLay:MKCircle = MKCircle(center: coor, radius: 100)
self.mapView?.addOverlay(overLay)
/*
// 添加水印
let url:URL = Bundle.main.url(forResource: "test", withExtension: "jpeg")!
let titleOverlay:MKTileOverlay = MKTileOverlay(urlTemplate: url.description)
self.mapView?.addOverlay(titleOverlay)
*/
}
}
//创建真正的图层
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
// //定义图层级
// let circle:MKCircleRenderer = MKCircleRenderer(circle: overlay as! MKCircle)
// circle.fillColor = UIColor.brown
// circle.strokeColor = UIColor.clear
// circle.alpha = 0.3
// return circle
//定义水印图层
let titleRenderer = MKTileOverlayRenderer(overlay: overlay as! MKTileOverlay)
titleRenderer.alpha = 0.1
return titleRenderer
}
6.开启方向识别
let lineView = UIView(frame: CGRect(x: screenWidth/2, y:0, width: 0.5, height: screenHeight))
lineView.backgroundColor = .black
self.view.addSubview(lineView)
self.compassLayer = CALayer()
self.compassLayer?.frame = CGRect(x:( screenWidth - 50)/2, y: ( screenHeight - 50)/2, width: 50, height: 50)
//把图片显示到layer上
self.compassLayer?.contents = UIImage(named: "icon-info")?.cgImage
self.view.layer.addSublayer(self.compassLayer!)
if CLLocationManager.headingAvailable() {
print("headingAvailable is ture")
self.loationManager = CLLocationManager()
self.loationManager?.delegate = self
self.loationManager?.startUpdatingHeading()//开启方向识别
}
func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
let heding:Double = -1 * M_1_PI * newHeading.magneticHeading / 180.0 //将设备方向转换为弧度
//print("didUpdateHeading \(heding)")
let rocationAnimation:CABasicAnimation = CABasicAnimation(keyPath: "transform")
let fromValue:CATransform3D = self.compassLayer!.transform
rocationAnimation.fromValue = NSValue(caTransform3D: fromValue)
let toValue:CATransform3D = CATransform3DMakeRotation(CGFloat(heding), 0.0, 0.0, 1.0)
rocationAnimation.toValue = NSValue(caTransform3D: toValue)
rocationAnimation.duration = 0.2
//动画结束后移除动画
rocationAnimation.isRemovedOnCompletion = true
self.compassLayer?.transform = toValue
//添加动画
self.compassLayer?.add(rocationAnimation, forKey: nil)
}
//允许开启定位方向识别
func locationManagerShouldDisplayHeadingCalibration(_ manager: CLLocationManager) -> Bool {
return true
}
7.简易导航系统
import UIKit
import CoreLocation
import MapKit
class ViewController: UIViewController,CLLocationManagerDelegate,MKMapViewDelegate{
var loationManager:CLLocationManager?
var mapView:MKMapView?
//出发地
var startTextFiled:UITextField?
var endTextFiled:UITextField?
var startButton:UIButton?
var gl:CLGeocoder?
//记录起始位置信息
var startCLPlacemark:CLPlacemark?
var mLocationInfo:CLLocation?
//线路图
var navigationPath: MKPolyline?
//添加锚点
var annotations = Array<MKAnnotation>()
override func viewDidLoad() {
super.viewDidLoad()
if CLLocationManager.locationServicesEnabled() { //判断设备是否支持定位服务
self.loationManager = CLLocationManager()
self.loationManager?.desiredAccuracy = kCLLocationAccuracyBest //设置定位到精确度
self.loationManager?.distanceFilter = 50 //设置定位距离
if #available(iOS 8.0, *){
print("\(UIDevice.current.systemVersion)")
//self.loationManager?.requestWhenInUseAuthorization() // 设置启用时间
self.loationManager?.requestAlwaysAuthorization() //一直启用
}
self.loationManager?.delegate = self
//是否开启定位
let status: CLAuthorizationStatus = CLLocationManager.authorizationStatus()
/**
* <key>NSLocationWhenInUseUsageDescription</key>
*<string>应用程序在前台运行时请求访问用户位置信息</string>
*<key>NSLocationAlwaysUsageDescription</key>
*<string>应用程序总是请求访问用户的位置</string>
*/
if ( status == .authorizedAlways ||
status == .authorizedWhenInUse){
self.loationManager?.startUpdatingLocation() //开启定位
}
}
let screenWidth = UIScreen.main.bounds.width
let screenHeight = UIScreen.main.bounds.height
//初始化地图控件
self.mapView = MKMapView(frame: CGRect(x: 0, y: 0, width: screenWidth, height: screenHeight))
self.mapView?.mapType = .standard //标准导航
self.mapView?.isScrollEnabled = true
self.mapView?.isZoomEnabled = true
self.mapView?.isRotateEnabled = true
self.mapView?.delegate = self
self.view.addSubview(self.mapView!)
self.startTextFiled = UITextField(frame: CGRect(x: 10, y: 50, width: 120, height: 50))
self.startTextFiled?.borderStyle = .roundedRect
self.startTextFiled?.font = UIFont.systemFont(ofSize: CGFloat(12))
self.startTextFiled?.textColor = UIColor.white
self.startTextFiled?.placeholder = "出发地"
self.endTextFiled = UITextField(frame: CGRect(x: 150, y: 50, width: 120, height: 50))
self.endTextFiled?.borderStyle = .roundedRect
self.endTextFiled?.font = UIFont.systemFont(ofSize: CGFloat(12))
self.endTextFiled?.textColor = UIColor.white
self.endTextFiled?.placeholder = "目的地"
self.startButton = UIButton(frame: CGRect(x: 280, y: 50, width: 80, height: 50))
self.startButton?.titleLabel?.font = UIFont.systemFont(ofSize: CGFloat(12))
self.startButton?.layer.cornerRadius = 5.0
self.startButton?.layer.borderWidth = 0.5
self.startButton?.layer.borderColor = UIColor.black.cgColor
self.startButton?.setTitle("开始导航", for: UIControl.State.normal)
self.view.addSubview(self.startTextFiled!)
self.view.addSubview(self.endTextFiled!)
self.view.addSubview(self.startButton!)
self.startButton?.addTarget(self, action: #selector(self.startGeocodeAddress(sender:)), for: UIControl.Event.touchUpInside)
self.gl = CLGeocoder()
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
switch status {
case .notDetermined:
print("用户尚未对此应用程序做出选择")
case .restricted:
print("系统定位服务功能被限制")
case .denied:
print("用户禁止访问定位")
case .authorizedAlways:
self.loationManager?.startUpdatingLocation() //开启定位
case .authorizedWhenInUse:
self.loationManager?.startUpdatingLocation() //开启定位
case .authorized:
self.loationManager?.startUpdatingLocation() //开启定位
@unknown default:
print("unknown")
}
}
@objc func startGeocodeAddress(sender : AnyObject){
self.startTextFiled?.resignFirstResponder()
self.endTextFiled?.resignFirstResponder()
if self.startTextFiled!.text!.isEmpty || self.endTextFiled!.text!.isEmpty {
let alertView = UIAlertController(title: nil, message: "出发地或者目的地为空", preferredStyle: UIAlertController.Style.alert)
alertView.addAction(UIAlertAction(title: "确定", style: UIAlertAction.Style.cancel, handler: { _ in
self.dismiss(animated: true, completion: nil)
}))
self.present(alertView, animated: true, completion: nil)
}else {
//print("startTextFiled=\(self.startTextFiled!.text!.description) ,endTextFiled=\(self.endTextFiled!.text!.description)")
if self.startTextFiled!.text?.description == "我的位置" {
self.gl?.reverseGeocodeLocation(self.mLocationInfo!, completionHandler: {(placemarks:[CLPlacemark]!, err: Error! ) in
if placemarks.count > 0{
let startPlaceMark:CLPlacemark = placemarks[0] as CLPlacemark
//print(" start locality= \(startPlaceMark.locality!.description)")
self.startCLPlacemark = startPlaceMark
//滚动到指定位置
self.locationLatitudeAndLongitude(latitude: self.startCLPlacemark!.location!.coordinate.latitude, longitude: self.startCLPlacemark!.location!.coordinate.longitude)
self.annotations.append(self.addMapViewAnnotaion(latitude: self.startCLPlacemark!.location!.coordinate.latitude, longitude: self.startCLPlacemark!.location!.coordinate.longitude, title: "出发地"))
//编码目的地
self.gl!.geocodeAddressString(self.endTextFiled!.text!.description, completionHandler: { (placemarks:[CLPlacemark]!, err: Error! ) in
if placemarks.count > 0{
let endPlaceMark:CLPlacemark = placemarks[0] as CLPlacemark
//print(" end locality= \(endPlaceMark.locality!.description)")
self.startNavigation(endPlaceMark: endPlaceMark)
}
})
}
})
}else {
//编码出发地
self.gl!.geocodeAddressString(self.startTextFiled!.text!.description, completionHandler: {(placemarks:[CLPlacemark]!, err: Error! ) in
if placemarks.count > 0{
let startPlaceMark:CLPlacemark = placemarks[0] as CLPlacemark
self.startCLPlacemark = startPlaceMark
self.locationLatitudeAndLongitude(latitude: self.startCLPlacemark!.location!.coordinate.latitude, longitude: self.startCLPlacemark!.location!.coordinate.longitude)
self.annotations.append(self.addMapViewAnnotaion(latitude: self.startCLPlacemark!.location!.coordinate.latitude, longitude: self.startCLPlacemark!.location!.coordinate.longitude, title: "出发地"))
//编码目的地
self.gl!.geocodeAddressString(self.endTextFiled!.text!.description, completionHandler: { (placemarks:[CLPlacemark]!, err: Error! ) in
if placemarks.count > 0{
let endPlaceMark:CLPlacemark = placemarks[0] as CLPlacemark
self.startNavigation(endPlaceMark: endPlaceMark)
}
})
}
})
}
}
}
//正式启动导航
func startNavigation(endPlaceMark:CLPlacemark){
//移除上次定位地图
if(self.navigationPath != nil){
self.mapView?.removeOverlay(self.navigationPath!)
}
self.annotations.append(self.addMapViewAnnotaion(latitude: endPlaceMark.location!.coordinate.latitude, longitude: endPlaceMark.location!.coordinate.longitude, title: "目的地"))
self.mapView?.addAnnotations(self.annotations)
//设置出发地和目的地
let request:MKDirections.Request = MKDirections.Request()
let mkPlacemark:MKPlacemark = MKPlacemark(placemark: self.startCLPlacemark!)
request.source = MKMapItem(placemark: mkPlacemark)
let endMkPlacemark:MKPlacemark = MKPlacemark(placemark: endPlaceMark)
request.destination = MKMapItem(placemark: endMkPlacemark)
let direction:MKDirections = MKDirections(request: request)
direction.calculate { (response:MKDirections.Response!, err:Error!) in
print("------routes------\(response.routes.count)")
//这里应该会有多条线路,测试时取其中一条
let route:MKRoute = response.routes[0] as MKRoute
self.navigationPath = route.polyline
//添加地图线路
self.mapView!.addOverlay(self.navigationPath!, level: MKOverlayLevel.aboveLabels)
}
}
//定位失败
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("locationManager =\(error.localizedDescription)")
}
/*设置精确位置*/
func locationLatitudeAndLongitude(latitude:Double ,longitude:Double){
let coordinate2d:CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
//设置一个精确范围,值越小精确度越高
let span :MKCoordinateSpan = MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta:0.01)
let region:MKCoordinateRegion = MKCoordinateRegion(center: coordinate2d, span: span)
self.mapView?.setRegion(region, animated: true)
}
// 添加锚点
func addMapViewAnnotaion(latitude:Double ,longitude:Double,title:String) -> MKPointAnnotation{
let annotaion:MKPointAnnotation = MKPointAnnotation()
let coordinate2d:CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
annotaion.coordinate = coordinate2d
annotaion.title = title
return annotaion
}
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let mkpolyLine = MKPolylineRenderer(overlay: overlay as! MKPolyline)
mkpolyLine.lineWidth = 5
mkpolyLine.strokeColor = UIColor.blue
return mkpolyLine
}
//定位成功
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if locations.count > 0 {
//获取最新的定位信息
let locationInfo:CLLocation = locations.last! as CLLocation
//设置到指定位置
self.locationLatitudeAndLongitude(latitude: locationInfo.coordinate.latitude, longitude: locationInfo.coordinate.longitude)
self.startTextFiled?.text = "我的位置"
self.mLocationInfo = locationInfo
}
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
print("viewFor annotation")
let identy:String = "identy"
var pinView:MKPinAnnotationView? = mapView.dequeueReusableAnnotationView(withIdentifier: identy) as? MKPinAnnotationView
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identy)
}
if annotation.title == "出发地" {
pinView?.pinTintColor = UIColor.green
}else {
pinView?.pinTintColor = UIColor.red
}
return pinView
}
}
image.png