初识iOS 定位

2022-05-05  本文已影响0人  gale_小米
  1. CClocationManager 用于启动和停止向应用程序传递位置相关事件的对象。
  2. 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
上一篇下一篇

猜你喜欢

热点阅读