Search code examples
swiftmapkitcllocationmanager

Swift warning making UI unresponsive


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


Solution

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