UI Responsiveness error: guard CLLocationManager.locationServicesEnabled() else method can cause UI unresponsiveness if invoked on the main thread.

I'm working on a weather and news app, and when I run the app on my device, it says "This method can cause UI unresponsiveness if invoked on the main thread. Instead, consider waiting for the -locationManagerDidChangeAuthorization: callback and checking authorizationStatus first." I am getting the error, what should I do?

This error message appears on two lines with the CLLocationManager.locationServicesEnabled() else { method.

I have added the codes of the page where I got the error below.

I am using openweathermap API as weather API and newsapi API as news API.

import Foundation
import CoreLocation
import Combine

typealias LocationNameResultType = Result<String, Error>

class WeatherService: WeatherServiceProtocol {
    
private let apiProvider = APIProvider<WeatherEndpoint>()

private let locationManager = CLLocationManager()

private lazy var location: CLLocation? = locationManager.location

init() {
    startUpdatingLocation()
}

func getCityName(completion: @escaping (LocationNameResultType) -> Void) {
    guard let location = location else {
        completion(.failure(WeatherServiceErrors.locationNil))
        return
    }
    
    let geocoder = CLGeocoder()
    geocoder.reverseGeocodeLocation(location) { (placemarks, error) in
        if let error = error {
            completion(.failure(error))
        }
        
        guard let placemark = placemarks?.first,
            let cityName = placemark.locality else {
            completion(.failure(WeatherServiceErrors.placeMarkNil))
            return
        }
        
        completion(.success(cityName))
    }
}

func requestCurrentWeather() -> AnyPublisher<Data, Error> {
    locationManager.requestWhenInUseAuthorization()
    
    guard CLLocationManager.locationServicesEnabled() else {
        return Fail(error: WeatherServiceErrors.userDeniedWhenInUseAuthorization)
            .eraseToAnyPublisher()
    }
    locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
    locationManager.startUpdatingLocation()
    
    guard let location = location else {
        return Fail(error: WeatherServiceErrors.locationNil)
            .eraseToAnyPublisher()
    }
    
    return apiProvider.getData(
        from: .getCurrentWeather(latitude: location.coordinate.latitude,
                                 longitude: location.coordinate.longitude)
    )
        .eraseToAnyPublisher()
}

deinit {
    stopUpdatingLocation()
}

}

private extension WeatherService {
    func startUpdatingLocation() {
        locationManager.requestWhenInUseAuthorization()
    guard CLLocationManager.locationServicesEnabled() else {
        return
    }
    locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
    locationManager.startUpdatingLocation()
}

func stopUpdatingLocation() {
    locationManager.stopUpdatingLocation()
}

}

Replies

I think this warning is saying exactly what it means: It’s not OK to call CLLocationManager.locationServicesEnabled() from the main thread. This method can take a while to come back, so calling it on the main thread puts you at risk of UI responsiveness problems.

You have two options:

  • Call it from a secondary thread.

  • Not call it at all.

The latter is the easiest. As it says in the docs:

You are not required to call locationServicesEnabled(). However, If you wish to display instructions about enabling location services …

So, unless you need to provide that level of detail, you can avoid this call completely.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"