Home > OS >  Swift warning making UI unresponsive
Swift warning making UI unresponsive

Time:11-17

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

CodePudding user response:

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.

CodePudding user response:

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