Domain=kCLErrorDomain Code=8 when fetching location through zipcode

272 views Asked by At

I'm trying to fetch the the latitude and longitude based on the input parameters postal/city and country code. Below is my code, this works fine if enter City and country name but shows error if I enter zipcode and country code. Below is the code. (Note: Location services and app permissions are enabled)

func getLocationFrom(postalCityCode: String, countryCode: String) -> CLLocation? {
        let geocoder = CLGeocoder()
        var location: CLLocation?
        let address = CNMutablePostalAddress()
        address.postalCode = postalCityCode
        address.country = countryCode
        geocoder.geocodePostalAddress(address, preferredLocale: Locale.current) { (placemarks, error) in
            guard error == nil else {
                print("Error: \(error!)")
                return
            }
            guard let placemark = placemarks?.first else {
                print("Error: placemark is nil")
                return
            }
            guard let coordinate = placemark.location?.coordinate else {
                print("Error: coordinate is nil")
                return
            }
            location = CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude)
            print("Found location = \(location)")
        }
        return location
    }

Working input: Shanghai, CN

Failing input: 200040, CN

Edit

Attached updated code as suggested in the answer but still experiencing same issue

enter image description here

1

There are 1 answers

9
workingdog support Ukraine On BEST ANSWER

Currently, you are using return location before it is set, since geocoder.geocodePostalAddress(...) is an asynchronous function.

That means you need to use a completion handler (for example) to return the location, when it has the results, something like this:

func getLocationFrom(postalCityCode: String, countryCode: String, completion: @escaping ( CLLocation?) -> Void) {
    
    let geocoder = CLGeocoder()
    var location: CLLocation?
    let address = CNMutablePostalAddress()
    address.postalCode = postalCityCode
    address.country = countryCode
    geocoder.geocodePostalAddress(address, preferredLocale: Locale.current) { (placemarks, error) in
        guard error == nil else {
            print("Error: \(error!)")
            return completion(nil)
        }
        guard let placemark = placemarks?.first else {
            print("Error: placemark is nil")
            return completion(nil)
        }
        guard let coordinate = placemark.location?.coordinate else {
            print("Error: coordinate is nil")
            return completion(nil)
        }
        location = CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude)
        print("\n--> Found location = \(location) \n")
        completion(location)   // <-- here
    }
}
    

Use it like this:

 getLocationFrom(postalCityCode: "200040", countryCode: "CN") { location in
     print("\n---> location: \(location) \n")
 }
 
 

EDIT-1

for testing and isolating the issue, try this code in a new SwiftUI project:

struct ContentView: View {
    @State var cityLocation = CLLocation()

    var body: some View {
        Text(cityLocation.description)
            .onAppear {
                getLocationFrom(postalCityCode: "200040", countryCode: "CN") { location in
                    print("\n---> location: \(location) \n")
                    if let theLocation = location {
                        cityLocation = theLocation
                    }                    
                }
            }
    }
    
    func getLocationFrom(postalCityCode: String, countryCode: String, completion: @escaping ( CLLocation?) -> Void) {
        
        let geocoder = CLGeocoder()
        var location: CLLocation?
        let address = CNMutablePostalAddress()
        address.postalCode = postalCityCode
        address.country = countryCode
        geocoder.geocodePostalAddress(address, preferredLocale: Locale.current) { (placemarks, error) in
            guard error == nil else {
                print("Error: \(error!)")
                return completion(nil)
            }
            guard let placemark = placemarks?.first else {
                print("Error: placemark is nil")
                return completion(nil)
            }
            guard let coordinate = placemark.location?.coordinate else {
                print("Error: coordinate is nil")
                return completion(nil)
            }
            location = CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude)
            print("\n--> Found location = \(location) \n")
            completion(location)
        }
    }
}