0
votes

I have build an iOS app using swift.

I implemented the core location and mapview in my apps. For the first time, it could run smoothly without any problem (on simulator or iPhone).

The app could work properly and could get the current location from my iPhone. But, every thing change when I try to add GPX location in the Xcode (I want to try using any location with the GPX File). After I add the GPX file and select it as simulator location, my app always crash and the CLLocationManager always returning nil value.

I think the problem only exist for the simulator, but I did happen in my iPhone too. The problem is still exist even after I delete the GPX file.

I always get an 'EXC_BAD_INSTRUCTION' whenever I want to get the latitude and longitude value.

this is my code :

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)

for your information, previously the app was working properly with this code

please help me

PS: this is my complete code

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.
}
*/

}

this is my point annotation class

class MyPointAnnotation : MKPointAnnotation {
var pinTintColor: UIColor?

}

3
Why don't implement the didUpdateLocations CLLocationManagerDelegatemethod?Reinier Melian
previously it can run smoothly without didUpdateLocationschrist2702
I already implement the didupdatelocations, but still give an errorchrist2702
Your problem is that CLLocationManager maybe don´t have any position yet, so you are forcing unwrap values that are maybe nil, in didUpdateLocations this will not happen anymore, because this method is called when CLLocationManager have defined positionReinier Melian
Can you post your entire code for this viewController?, you need set your lokasiAwal value inside didUpdateLocations once CLLocationManager get valid positionReinier Melian

3 Answers

0
votes

As I said in my comments: Your problem is that CLLocationManager maybe don´t have any position yet, so you are forcing unwrap values that are maybe nil, in didUpdateLocations this will not happen anymore, because this method is called when CLLocationManager have defined position

The main change in your code is

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 
            }
        }
    }

Complete Code

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()

        }
    }
}

Hope this helps

0
votes

Use CoreLocation delegate in viewdidload & get coordinates in 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)
    }

}
0
votes

Your problem is that CLLocationManager maybe don´t have any position yet. delegate method didUpdateLocations will called when datas are ready.

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