1

I am using swift version 5.7.1 and Xcode 14.1 . I am creating Map Application with user location and it working fine .. But here is the problem , it giving warning .. This method can cause UI unresponsiveness if invoked on the main thread. Instead, consider waiting for the -locationManagerDidChangeAuthorization: callback and checking authorizationStatus first..

On this line .. if CLLocationManager.locationServicesEnabled() {

I already added into main thread. but still same warning .. Here is the code ..

class ViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate {
    
    let mapView = MKMapView()
    let manager = CLLocationManager()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        mapView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(mapView)
        mapView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        mapView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        mapView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        mapView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        manager.requestAlwaysAuthorization()
        manager.requestWhenInUseAuthorization()

        if CLLocationManager.locationServicesEnabled() {
            DispatchQueue.main.async {
                self.manager.delegate = self
                self.manager.desiredAccuracy = kCLLocationAccuracyBest
                
                self.manager.startUpdatingLocation()
                self.mapView.delegate = self
                self.mapView.mapType = .standard
                self.mapView.isZoomEnabled = true
                self.mapView.isScrollEnabled = true
                self.mapView.showsUserLocation = false
            }  
        }
        
        if let coor = mapView.userLocation.location?.coordinate{
            mapView.setCenter(coor, animated: true)
        }
    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations
                         locations: [CLLocation]) {
        
        guard let mylocation = manager.location else { return }
        
        let myCoordinates: CLLocationCoordinate2D = mylocation.coordinate
        
        mapView.mapType = MKMapType.standard
        
        let span = MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)
        let region = MKCoordinateRegion(center: myCoordinates, span: span)
        mapView.setRegion(region, animated: true)
        // comment pin object if showsUserLocation = true
        let pin = MKPointAnnotation()
        pin.coordinate = myCoordinates
        pin.title = "You are here"
        mapView.addAnnotation(pin)
    }
}

Here is the screenshot ..

Warning

Fabio
  • 5,432
  • 4
  • 22
  • 24
  • We're getting that too. Laugh uproariously and move on. I mean, come on, we're getting that warning on the App Delegate for heaven's sake! This is obviously spurious. – matt Nov 16 '22 at 15:08
  • Did you consider doing what it very clearly says to do in the error message? – Fogmeister Nov 16 '22 at 15:17
  • I have removed the code .. to check is it running successfully or not .. And it working fine .. But question is here if it run into main thread it shouldn’t show the warning .. –  Nov 16 '22 at 15:19
  • The problem can occur when it is run on the main thread. If you are running it on the main thread then that is why you are seeing that error. Use the other function that it mentions. – Fogmeister Nov 16 '22 at 15:24
  • can you please suggest few link for this function implementation .. locationManagerDidChangeAuthorization(_:). and authorizationStatus ..??? –  Nov 16 '22 at 15:28
  • Without calling CLLocationManager.locationServicesEnabled() function it working fine , but not sure does it cause any other issue –  Nov 16 '22 at 15:30
  • Does this answer your question? [How should CLLocationManager status be checked in locationManagerDidChangeAuthorization before loading an iOS view?](https://stackoverflow.com/questions/74141609/how-should-cllocationmanager-status-be-checked-in-locationmanagerdidchangeauthor) – HangarRash Nov 16 '22 at 16:43

2 Answers2

1

The warning tells you that your should not call CLLocationManager.locationServicesEnabled() at all, as it can take a long time and cause UI hiccups. Instead, you should implement the delegation function locationManagerDidChangeAuthorization(_:), check the authorizationStatus and store the result somewhere, then use that stored value in your if.

DarkDust
  • 90,870
  • 19
  • 190
  • 224
  • can you please suggest few link for this function implementation .. locationManagerDidChangeAuthorization(_:). and authorizationStatus ..??? –  Nov 16 '22 at 15:35
  • See [this answer](https://stackoverflow.com/a/74142296/400056) for more details. – DarkDust Nov 16 '22 at 15:45
0

Try this with locationManagerDidChangeAuthorization:

class Prova: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate {

let mapView = MKMapView()
let manager = CLLocationManager()

override func viewDidLoad() {
    super.viewDidLoad()
    mapView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(mapView)
    mapView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
    mapView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
    mapView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
    mapView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
    
    locationAuthorization()
}

func locationAuthorization(){
    switch manager.authorizationStatus {
    case .authorizedWhenInUse:
        print("Authorized")
        determineMyCurrentLocation()
    case .denied:
       break
    case .authorizedAlways:
        determineMyCurrentLocation()
    case.notDetermined:
        manager.requestAlwaysAuthorization()
        manager.requestWhenInUseAuthorization()
        sleep(2)
        locationAuthorization()
    default:
        break
    }
}

func determineMyCurrentLocation() {
    print("determine current location")
    if CLLocationManager.locationServicesEnabled() {
        DispatchQueue.main.async {
            self.manager.delegate = self
            self.manager.desiredAccuracy = kCLLocationAccuracyBest
            self.manager.startUpdatingLocation()
            self.mapView.delegate = self
            self.mapView.mapType = .standard
            self.mapView.isZoomEnabled = true
            self.mapView.isScrollEnabled = true
            self.mapView.showsUserLocation = false // if you want to show default pin
        }
    }
    
    if let coor = mapView.userLocation.location?.coordinate {
        mapView.setCenter(coor, animated: true)
    }
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
}

func locationManager(_ manager: CLLocationManager, didUpdateLocations
    locations: [CLLocation]) {
    
    guard let mylocation = manager.location else { return }
    
    let myCoordinates: CLLocationCoordinate2D = mylocation.coordinate

    mapView.mapType = MKMapType.standard

    let span = MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)
    let region = MKCoordinateRegion(center: myCoordinates, span: span)
    mapView.setRegion(region, animated: true)
    
    let pin = MKPointAnnotation()
    pin.coordinate = myCoordinates
    pin.title = "You are here"
    mapView.addAnnotation(pin)
 }
}
Fabio
  • 5,432
  • 4
  • 22
  • 24
  • Try with my new code.... I hope that's ok – Fabio Nov 16 '22 at 16:08
  • It seems to me we have remove CLLocationManager.locationServicesEnabled() function completely regardless we use the emun case or not to determine the current location .. –  Nov 16 '22 at 17:06