-1

I am trying to create an application with only a map view that has a "Show user location" button placed on it, which I implement with the help of MapKit. With a press of the button I would also like to get user coordinates and for that I employ CLLocationManagerDelegate methods that I have trouble running. I did set "Privacy - Location When In Use Usage Description" string in plist.

Here is the code of my MapViewController:

import UIKit
import MapKit
import CoreLocation

class MapViewController: UIViewController, CLLocationManagerDelegate {
    // MARK: - Properties
    @IBOutlet weak var mapView: MKMapView!
    let locationManager = CLLocationManager()
    
    var fetchedData = ""
    
    // MARK: - Lifecycle
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
    
    // MARK: - Actions
    // this puts user location on map
    @IBAction func showUserLocation() {
        // check for location tracing permissions first
        let authStatus = CLLocationManager.authorizationStatus()
        
        if authStatus == .notDetermined {
            locationManager.requestWhenInUseAuthorization()
            return
        } else if authStatus == .denied || authStatus == .restricted {
            showLocationServicesDeniedAlert()
            return
        }
        
        let region = MKCoordinateRegion(center: mapView.userLocation.coordinate, latitudinalMeters: 1000, longitudinalMeters: 1000)

        mapView.setRegion(mapView.regionThatFits(region), animated: true)
        
        getCoordinates()
    }
    
    // MARK: - Helper methods
    // handle permission errors
    func showLocationServicesDeniedAlert() {
        let alert = UIAlertController(title: "Paikannuspalvelut pois päältä", message: "Ole hyvä ja salli paikannuspalvelut tälle äpille.", preferredStyle: .alert)
        
        let okAction = UIAlertAction(title: "OK", style: .default, handler: nil)
        alert.addAction(okAction)
        
        present(alert, animated: true, completion: nil)
    }
    
    // get user coordinates
    func getCoordinates() {
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
        locationManager.startUpdatingLocation()
    }
    
}

// MARK: - MKMapViewDelegate
extension MapViewController: MKMapViewDelegate {
    
}

// MARK: - CLLocationManagerDelegate
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
    print("*** Location manager failed with error: \(error.localizedDescription)")
}

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    let newLocation = locations.last!
    print("*** didUpdateLocations \(newLocation)")
}
E_net4
  • 27,810
  • 13
  • 101
  • 139
qlep
  • 15
  • 5

3 Answers3

0

when app runs make sure Location is not set to "None".

enter image description here

you can find these options on status bar when the simulator is active.

0

Thanks everyone for the input! As soon as I moved CLLocationManagerDelegate methods INSIDE view controller class everything started to work properly.

qlep
  • 15
  • 5
0

I gather that you successfully discovered that you need to put these methods inside the view controller. Excellent.

But I might suggest adding the protocol conformance in an extension of your class, not in the main implementation. This keeps your code nicely organized. For example:

import UIKit
import MapKit
import CoreLocation

class MapViewController: UIViewController {
    // MARK: - Properties

    ...
    
    // MARK: - Lifecycle

    override func viewDidLoad() { ... }
    
    // MARK: - Actions

    // this puts user location on map
    @IBAction func showUserLocation() { ... }
    
    // MARK: - Helper methods

    // handle permission errors
    func showLocationServicesDeniedAlert() { ... }
    
    // get user coordinates
    func getCoordinates() { ... } 
}

// MARK: - MKMapViewDelegate

extension MapViewController: MKMapViewDelegate { ... }

// MARK: - CLLocationManagerDelegate

extension MapViewController: CLLocationManagerDelegate {
    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        print("*** Location manager failed with error: \(error.localizedDescription)")
    }
    
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        let newLocation = locations.last!
        print("*** didUpdateLocations \(newLocation)")
    }
}
Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • Thank you for your suggestion, @Rob! I'll do that. It's funny how the hint for this solution was right before my eyes in form of that `MKMapViewDelegate` extension stub. – qlep Jul 26 '20 at 11:37