CLLocationManager 总是崩溃并返回 nil 值

CLLocationManager always crash and returning nil value

我已经使用 swift 构建了一个 iOS 应用程序。

我在我的应用程序中实现了核心位置和地图视图。第一次可以顺利运行,没有任何问题(在模拟器上或者iPhone)。

该应用程序可以正常运行,并且可以从我的 iPhone 获取当前位置。但是,当我尝试在 Xcode 中添加 GPX 位置时,一切都会发生变化(我想尝试将任何位置与 GPX 文件一起使用)。在我添加 GPX 文件并将其 select 作为模拟器位置后,我的应用程序总是崩溃并且 CLLocationManager 总是返回 nil 值。

我认为这个问题只存在于模拟器中,但我的 iPhone 也确实发生过。删除GPX文件后问题依旧

每当我想获取纬度和经度值时,我总是得到 'EXC_BAD_INSTRUCTION'。

这是我的代码:

let corLoc = CLLocationManager()

    //let corLoc2 = CLLocationManager()


    corLoc.delegate = self
    let statusLoc = CLLocationManager.authorizationStatus()
    if statusLoc == .notDetermined{
        corLoc.requestWhenInUseAuthorization()
    }
    corLoc.desiredAccuracy = kCLLocationAccuracyBest

    corLoc.startUpdatingLocation()

    let lokasiAwal = CLLocationCoordinate2D(latitude: (corLoc.location?.coordinate.latitude)!, longitude: (corLoc.location?.coordinate.longitude)!) //<--- always return EXC_BAD_INSTRUCTION


    let lokasiAkhir = CLLocationCoordinate2D(latitude: -7.299356, longitude: 112.676108)

供您参考,之前应用程序使用此代码可以正常工作

请帮帮我

PS: 这是我的完整代码

class LocationViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {


@IBOutlet weak var mapRoute: MKMapView!
var lokasiAwal2 = CLLocation()



func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    let userLocation:CLLocation = locations[0] as CLLocation
    // manager.stopUpdatingLocation()
    lokasiAwal2 = userLocation

}

func locationManager(manager: CLLocationManager!, didChangeAuthorizationStatus status: CLAuthorizationStatus) {

    if status == CLAuthorizationStatus.authorizedWhenInUse || status == CLAuthorizationStatus.authorizedAlways {

        manager.startUpdatingLocation()

    }
}


override func viewDidLoad() {
    super.viewDidLoad()
    mapRoute.delegate = self

    let corLoc = CLLocationManager()

    //let corLoc2 = CLLocationManager()


    corLoc.delegate = self
    let statusLoc = CLLocationManager.authorizationStatus()
    if statusLoc == .notDetermined{
        corLoc.requestWhenInUseAuthorization()
    }
    corLoc.desiredAccuracy = kCLLocationAccuracyBest

    corLoc.startUpdatingLocation()

    //let lokasiAwal = CLLocationCoordinate2D(latitude: (corLoc.location?.coordinate.latitude)!, longitude: (corLoc.location?.coordinate.longitude)!)

    let lokasiAwal = CLLocationCoordinate2D(latitude: lokasiAwal2.coordinate.latitude, longitude: lokasiAwal2.coordinate.longitude)


    //let lokasiAwal = CLLocationCoordinate2D(latitude: -7.263056, longitude: 112.740317)

    let lokasiAkhir = CLLocationCoordinate2D(latitude: -7.299356, longitude: 112.676108)
    //-7.299356, 112.676108 NH
    //-7.289182, 112.676104 PTC
    //-7.282713, 112.687633 bandar jakarta
    //-7.263056, 112.740317 TP

    //placemark
    let awalPlaceMark = MKPlacemark(coordinate: lokasiAwal, addressDictionary: nil)
    let akhirPlaceMark = MKPlacemark(coordinate: lokasiAkhir, addressDictionary: nil)

    let awalMap = MKMapItem(placemark: awalPlaceMark)
    let akhirMap = MKMapItem(placemark: akhirPlaceMark)


    //anotasi
    let awalAnotasi = MKPointAnnotation()
    awalAnotasi.title = "Your Location"


    //let awalPin = MKPinAnnotationView.init(annotation: awalAnotasi, reuseIdentifier: "Your Location")
    //awalPin.pinTintColor = UIColor.blue


    if let locationAwal = awalPlaceMark.location {
        awalAnotasi.coordinate = locationAwal.coordinate
    }

    let akhirAnotasi = MKPointAnnotation()
    akhirAnotasi.title = "National Hospital"

    if let locationAkhir = akhirPlaceMark.location {
        akhirAnotasi.coordinate = locationAkhir.coordinate
    }

    let awalPin = MyPointAnnotation()
    awalPin.coordinate = awalAnotasi.coordinate
    awalPin.pinTintColor = .green
    awalPin.title = awalAnotasi.title

    let akhirPin = MyPointAnnotation()
    akhirPin.coordinate = akhirAnotasi.coordinate
    akhirPin.pinTintColor = .blue
    akhirPin.title = akhirAnotasi.title

    //titik marker
    self.mapRoute.showAnnotations([awalPin, akhirPin], animated: true)


    //menambahkan route
    let directionRequest = MKDirectionsRequest()
    directionRequest.source = awalMap
    directionRequest.destination = akhirMap
    directionRequest.transportType = .automobile

    let directions = MKDirections(request: directionRequest)
    directions.calculate
        {
            (response, error) -> Void in

            guard let response = response else
            {
                if let error = error {
                    print("Error : \(error)")
                }
                return
            }

            let route = response.routes[0]


            self.mapRoute.add((route.polyline), level: MKOverlayLevel.aboveRoads)

            let rect = route.polyline.boundingMapRect
            self.mapRoute.setRegion(MKCoordinateRegionForMapRect(rect), animated: true)
            self.mapRoute.delegate = self

    }
    // Do any additional setup after loading the view.
}

func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
    let renderer = MKPolylineRenderer(overlay: overlay)
    renderer.lineWidth = 1.0
    renderer.strokeColor = UIColor.red

    return renderer
}

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {

    var annotView = mapView.dequeueReusableAnnotationView(withIdentifier: "myAnnotation") as? MKPinAnnotationView
    if annotView == nil {
        annotView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "myAnnotation")
    }
    else {
        annotView?.annotation = annotation
    }
    if let annotation = annotation as? MyPointAnnotation {
        annotView?.pinTintColor = annotation.pinTintColor
        annotView?.canShowCallout = true
    }

   return annotView
}



override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


/*
// MARK: - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    // Get the new view controller using segue.destinationViewController.
    // Pass the selected object to the new view controller.
}
*/

}

这是我的点注释class

class MyPointAnnotation : MKPointAnnotation {
var pinTintColor: UIColor?

}

viewdidload 中使用 CoreLocation 委托并在 didUpdateLocations 中获取坐标

import UIKit
import CoreLocation

class ViewController: UIViewController,CLLocationManagerDelegate {

    let corLoc = CLLocationManager()

    override func viewDidLoad() {
        super.viewDidLoad()
        corLoc.delegate = self
        let statusLoc = CLLocationManager.authorizationStatus()
        if statusLoc == .notDetermined{
            corLoc.requestWhenInUseAuthorization()
        }
        corLoc.desiredAccuracy = kCLLocationAccuracyBest
        corLoc.startUpdatingLocation()

    }
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
      print((corLoc.location?.coordinate.latitude) ?? "No values")
        let lokasiAwal = CLLocationCoordinate2D(latitude: (corLoc.location?.coordinate.latitude)!, longitude: (corLoc.location?.coordinate.longitude)!) //
        let lokasiAkhir = CLLocationCoordinate2D(latitude: -7.299356, longitude: 112.676108)
    }

}

您的问题是 CLLocationManager 可能还没有任何职位。委托方法 didUpdateLocations 将在数据准备就绪时调用。

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    let userLocation:CLLocation = locations[0] as CLLocation
    // manager.stopUpdatingLocation()
    lokasiAwal = userLocation
}

正如我在评论中所说:你的问题是 CLLocationManager 可能还没有任何位置,所以你强制展开可能为 nil 的值,在 didUpdateLocations 中这不会不再发生,因为当 CLLocationManager 定义了位置

时调用此方法

代码的主要变化是

extension LocationViewController : CLLocationManagerDelegate
    {
        func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {

            if let location = locations.last
            {
                if((location.horizontalAccuracy) < CLLocationAccuracy(0))
                {
                    return
                }

                lokasiAwal2 = location

                 //Calling the method when we are sure that a position is getted
                self.updateUIAndGetDirection()
                self.corLoc.stopUpdatingLocation() //avoiding continue direction changes 
            }
        }
    }

完整代码

import UIKit
import CoreLocation
import MapKit

class LocationViewController: UIViewController  {


    @IBOutlet weak var mapRoute: MKMapView!
    var lokasiAwal2 = CLLocation()
    var corLoc = CLLocationManager()

    override func viewDidLoad() {
        super.viewDidLoad()
        mapRoute.delegate = self

        //let corLoc2 = CLLocationManager()


        corLoc.delegate = self
        let statusLoc = CLLocationManager.authorizationStatus()
        if statusLoc == .notDetermined{
            corLoc.requestWhenInUseAuthorization()
        }
        corLoc.desiredAccuracy = kCLLocationAccuracyBest

        corLoc.startUpdatingLocation()


        // Do any additional setup after loading the view.
    }


    func updateUIAndGetDirection()
    {
        //let lokasiAwal = CLLocationCoordinate2D(latitude: (corLoc.location?.coordinate.latitude)!, longitude: (corLoc.location?.coordinate.longitude)!)

        let lokasiAwal = CLLocationCoordinate2D(latitude: lokasiAwal2.coordinate.latitude, longitude: lokasiAwal2.coordinate.longitude)


        //let lokasiAwal = CLLocationCoordinate2D(latitude: -7.263056, longitude: 112.740317)

        let lokasiAkhir = CLLocationCoordinate2D(latitude: -7.299356, longitude: 112.676108)
        //-7.299356, 112.676108 NH
        //-7.289182, 112.676104 PTC
        //-7.282713, 112.687633 bandar jakarta
        //-7.263056, 112.740317 TP

        //placemark
        let awalPlaceMark = MKPlacemark(coordinate: lokasiAwal, addressDictionary: nil)
        let akhirPlaceMark = MKPlacemark(coordinate: lokasiAkhir, addressDictionary: nil)

        let awalMap = MKMapItem(placemark: awalPlaceMark)
        let akhirMap = MKMapItem(placemark: akhirPlaceMark)


        //anotasi
        let awalAnotasi = MKPointAnnotation()
        awalAnotasi.title = "Your Location"


        //let awalPin = MKPinAnnotationView.init(annotation: awalAnotasi, reuseIdentifier: "Your Location")
        //awalPin.pinTintColor = UIColor.blue


        if let locationAwal = awalPlaceMark.location {
            awalAnotasi.coordinate = locationAwal.coordinate
        }

        let akhirAnotasi = MKPointAnnotation()
        akhirAnotasi.title = "National Hospital"

        if let locationAkhir = akhirPlaceMark.location {
            akhirAnotasi.coordinate = locationAkhir.coordinate
        }

        let awalPin = MyPointAnnotation()
        awalPin.coordinate = awalAnotasi.coordinate
        awalPin.pinTintColor = .green
        awalPin.title = awalAnotasi.title

        let akhirPin = MyPointAnnotation()
        akhirPin.coordinate = akhirAnotasi.coordinate
        akhirPin.pinTintColor = .blue
        akhirPin.title = akhirAnotasi.title

        //titik marker
        self.mapRoute.showAnnotations([awalPin, akhirPin], animated: true)


        //menambahkan route
        let directionRequest = MKDirectionsRequest()
        directionRequest.source = awalMap
        directionRequest.destination = akhirMap
        directionRequest.transportType = .automobile

        let directions = MKDirections(request: directionRequest)
        directions.calculate
            {
                (response, error) -> Void in

                guard let response = response else
                {
                    if let error = error {
                        print("Error : \(error)")
                    }
                    return
                }

                let route = response.routes[0]


                self.mapRoute.add((route.polyline), level: MKOverlayLevel.aboveRoads)

                let rect = route.polyline.boundingMapRect
                self.mapRoute.setRegion(MKCoordinateRegionForMapRect(rect), animated: true)
                self.mapRoute.delegate = self

        }
    }


    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


    /*
     // MARK: - Navigation

     // In a storyboard-based application, you will often want to do a little preparation before navigation
     override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
     // Get the new view controller using segue.destinationViewController.
     // Pass the selected object to the new view controller.
     }
     */
}

extension LocationViewController : MKMapViewDelegate
{
    func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
        let renderer = MKPolylineRenderer(overlay: overlay)
        renderer.lineWidth = 1.0
        renderer.strokeColor = UIColor.red

        return renderer
    }

    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {

        var annotView = mapView.dequeueReusableAnnotationView(withIdentifier: "myAnnotation") as? MKPinAnnotationView
        if annotView == nil {
            annotView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "myAnnotation")
        }
        else {
            annotView?.annotation = annotation
        }
        if let annotation = annotation as? MyPointAnnotation {
            annotView?.pinTintColor = annotation.pinTintColor
            annotView?.canShowCallout = true
        }

        return annotView
    }

}

extension LocationViewController : CLLocationManagerDelegate
{
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {

        if let location = locations.last
        {
            if((location.horizontalAccuracy) < CLLocationAccuracy(0))
            {
                return
            }

            lokasiAwal2 = location

            self.updateUIAndGetDirection()
            self.corLoc.stopUpdatingLocation() //avoiding continue direction changes 
        }
    }

    func locationManager(manager: CLLocationManager!, didChangeAuthorizationStatus status: CLAuthorizationStatus) {

        if status == CLAuthorizationStatus.authorizedWhenInUse || status == CLAuthorizationStatus.authorizedAlways {

            manager.startUpdatingLocation()

        }
    }
}

希望这对您有所帮助