Search code examples
iosclgeocoder

CLGeocoder error. GEOErrorDomain Code=-3


When I tried to use reverse geocoding,this error message showed up.

Geocode error: Error Domain=GEOErrorDomain Code=-3 "(null)"

My code is below:

import CoreLocation
geocoder.reverseGeocodeLocation(location) { (placemarks, error) in
    if let placemarks = placemarks {
        reverseGeocodeLocations[hash] = placemarks
    }
    callback(placemarks, error)
}

This works only time to time, and I request reverseGeocode several times per seconds. So I guess this error message is related to the limit of request or something? Is there any documentation about apple’s geocode request? Thanks for advance.


Updated

here is my entire code for requesting

import CoreLocation

fileprivate struct ReverseGeocodeRequest {

    private static let geocoder = CLGeocoder()
    private static var reverseGeocodeLocations = [Int: [CLPlacemark]]()
    private static let reverseGeocodeQueue = DispatchQueue(label: "ReverseGeocodeRequest.reverseGeocodeQueue")

    private static var nextPriority: UInt = 0

    fileprivate static func request(location: CLLocation, callback: @escaping ([CLPlacemark]?, Error?)->Void) {
        let hash = location.hash
        if let value = reverseGeocodeLocations[hash] {
            callback(value, nil)
        } else {
            reverseGeocodeQueue.async {
                guard let value = reverseGeocodeLocations[hash] else {
                    geocoder.reverseGeocodeLocation(location) { (placemarks, error) in
                        if let placemarks = placemarks {
                            reverseGeocodeLocations[hash] = placemarks
                        }
                        callback(placemarks, error)
                    }
                    return
                }
                callback(value, nil)
            }
        }
    }



    let priority: UInt
    let location: CLLocation
    let handler : ([CLPlacemark]?, Error?)->Void

    private init (location: CLLocation, handler: @escaping ([CLPlacemark]?, Error?)->Void) {
        ReverseGeocodeRequest.nextPriority += 1
        self.priority = ReverseGeocodeRequest.nextPriority
        self.location = location
        self.handler  = handler
    }

}

extension ReverseGeocodeRequest: Comparable {
    static fileprivate func < (lhs: ReverseGeocodeRequest, rhs: ReverseGeocodeRequest) -> Bool {
        return lhs.priority < rhs.priority
    }
    static fileprivate func == (lhs: ReverseGeocodeRequest, rhs: ReverseGeocodeRequest) -> Bool {
        return lhs.priority == rhs.priority
    }

}


extension CLLocation {

    func reverseGeocodeLocation(callback: @escaping ([CLPlacemark]?, Error?)->Void) {
        ReverseGeocodeRequest.request(location: self, callback: callback)
    }

    func getPlaceName(callback: @escaping (Error?, String?)->Void) {
        self.reverseGeocodeLocation { (placemarks, error) in
            guard let placemarks = placemarks, error == nil else {
                callback(error, nil)
                return
            }
            guard let placemark = placemarks.first else {
                callback(nil, "Mysterious place")
                return
            }

            if let areaOfInterest = placemark.areasOfInterest?.first {
                callback(nil, areaOfInterest)
            } else if let locality = placemark.locality {
                callback(nil, locality)
            } else {
                callback(nil, "On the Earth")
            }
        }
    }
}

Solution

  • After searching everywhere for the answer it was in Apples docs! :/

    https://developer.apple.com/reference/corelocation/clgeocoder/1423621-reversegeocodelocation

    Geocoding requests are rate-limited for each app, so making too many requests in a short period of time may cause some of the requests to fail. When the maximum rate is exceeded, the geocoder passes an error object with the value network to your completion handler.

    When checking the error code in the completion handler it is indeed Network Error:2

    Hope this helps someone!