Search code examples
iosswiftcore-locationclgeocoder

Domain=kCLErrorDomain Code=8 when fetching location through zipcode


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


Solution

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