2

I want to get the address from the coordinate. I have attached my code below..

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    let lastLocation = locations.last!
    let latvalue     = lastLocation.coordinate.latitude
    let lngvalue     = lastLocation.coordinate.longitude
    self.db_latvalue = latvalue
    self.db_lngvalue = lngvalue
    let location = CLLocation(latitude: latvalue, longitude:lngvalue)
    let address = CLGeocoder.init()
    address.reverseGeocodeLocation(CLLocation.init(latitude: latvalue, longitude:lngvalue)) { (places, error) in
        if error == nil{
            if let place = places{
                   print("addressshowingssq \(place)")
                self.db_address = "\(place)"

            }
        }
    }

Output:

[L-30 2nd A Main Road, L-30 2nd A Main Road, HSR Layout, Bengaluru, Karnataka 560102, India @ <+12.91597974,+77.62879254> +/- 100.00m, region CLCircularRegion (identifier:'<+12.91597974,+77.62879254> radius 70.94', center:<+12.91597974,+77.62879254>, radius:70.94m)]

I want only the address as i mention below

L-30 2nd A Main Road, L-30 2nd A Main Road, HSR Layout, Bengaluru, Karnataka 560102

I researched google i got different solution so i got confused.

Ashley Mills
  • 50,474
  • 16
  • 129
  • 160
Gowthaman M
  • 8,057
  • 8
  • 35
  • 54
  • 1
    Please show the solutions you have tried to get the address part. Did you read the documentation for `CLPlacemark`? Your first place to go should always be the Apple documentation. – Ashley Mills Oct 12 '18 at 10:18
  • see this for help: https://stackoverflow.com/questions/41358423/swift-generate-an-address-format-from-reverse-geocoding – Anbu.Karthik Oct 12 '18 at 10:19
  • `place` is a `CLPlacemark` object, you might want to look at its property instead of using it fully. Like `place.address`? – Larme Oct 12 '18 at 10:19
  • `if let place = places{ print("addressshowingssq \(place)") self.db_address = "\(place)" this is the one i tried }` – Gowthaman M Oct 12 '18 at 10:20

4 Answers4

6

Update

I have done a few modification to iVarun's solution. This is simpler. and working.

First, add this function:

func geocode(latitude: Double, longitude: Double, completion: @escaping (CLPlacemark?, Error?) -> ())  {
    CLGeocoder().reverseGeocodeLocation(CLLocation(latitude: latitude, longitude: longitude)) { completion($0?.first, $1) }
}

After that, get the address:

geocode(latitude: latvalue, longitude: lngvalue) { placemark, error in
    guard let placemark = placemark, error == nil else { return }
    // you should always update your UI in the main thread
    DispatchQueue.main.async {
        //  update UI here
        print("address1:", placemark.thoroughfare ?? "")
        print("address2:", placemark.subThoroughfare ?? "")
        print("city:",     placemark.locality ?? "")
        print("state:",    placemark.administrativeArea ?? "")
        print("zip code:", placemark.postalCode ?? "")
        print("country:",  placemark.country ?? "")
    }
}

Result:

address1: Rua Casuarina
address2: 443
city: Rio de Janeiro
state: RJ
zip code: 20975
country: Brazil

As @iOSer indicated, CLPlacemark is capable of giving you this part of the string, However.

You could split the string:

let output:String = "[L-30 2nd A Main Road, L-30 2nd A Main Road, HSR Layout, Bengaluru, Karnataka 560102, India @ <+12.91597974,+77.62879254> +/- 100.00m, region CLCircularRegion (identifier:'<+12.91597974,+77.62879254> radius 70.94', center:<+12.91597974,+77.62879254>, radius:70.94m)]"
let items = output.components(separatedBy: "@")
print(items[0])

Becuse the @ will be always included, you could skip the rest.

Result: R

excitedmicrobe
  • 2,338
  • 1
  • 14
  • 30
  • `@` as of `At` will be definitely included always if you use that as a output. try more locations and see if it has an `@` or not – excitedmicrobe Oct 12 '18 at 10:31
  • What means `L-30`? Why do you want twice `L-30 A Main Road`? Also using `description` of an object (that's what is doing `"\(place)"`) that's NOT recommended as Apple could change it in next iOS version. – Larme Oct 12 '18 at 13:03
  • @Larme, as of now; it’s the way to go; also I provided two options – excitedmicrobe Oct 12 '18 at 13:04
  • 1
    I disagree with that method. I'm not sure at all about that "Becuse the @ will be always included, you could skip the rest." too. Also, Apple could tomorrow reverse the order. – Larme Oct 12 '18 at 13:10
  • @Larme. I will update my code if “apple reversed” their code tomorrow – excitedmicrobe Oct 12 '18 at 13:48
3

Hope this will help you:

address.reverseGeocodeLocation(CLLocation.init(latitude: latvalue, longitude:lngvalue)) { (places, error) in
            if error == nil{
                let placeMark = places! as [CLPlacemark]

                if placeMark.count > 0 {
                    let placeMark = places![0]
                    var addressString : String = ""

                    if placeMark.subThoroughfare != nil {
                        addressString = addressString + placeMark.subThoroughfare! + ", "
                    }
                    if placeMark.thoroughfare != nil {
                        addressString = addressString + placeMark.thoroughfare! + ", "
                    }
                    if placeMark.subLocality != nil {
                        addressString = addressString + placeMark.subLocality! + ", "
                    }

                    if placeMark.locality != nil {
                        addressString = addressString + placeMark.locality! + ", "
                    }
                    if placeMark.administrativeArea != nil {
                        addressString = addressString + placeMark.administrativeArea! + ", "
                    }
                    if placeMark.country != nil {
                        addressString = addressString + placeMark.country! + ", "
                    }
                    if placeMark.postalCode != nil {
                        addressString = addressString + placeMark.postalCode! + " "
                    }

                    print(addressString)
                }
            }
        }

Output:

L-30, 2nd A Main Road, HSR Layout, Bengaluru, Karnataka, India, 560102

iVarun
  • 6,496
  • 2
  • 26
  • 34
  • Thanks you sir..i tired your answer this is also working fine...future i think i have to use your answer... – Gowthaman M Oct 12 '18 at 10:43
  • @GowthamanM Great that worked for you. Why you have accepted other answer then? as you said you are going to use my answer in future. – iVarun Oct 12 '18 at 10:46
  • @GowthamanM You should accept future proof code not simple one as you said you are going to use my code in future. Anyway both answer are correct. – iVarun Oct 12 '18 at 10:53
1

Swift 3

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    let locValue:CLLocationCoordinate2D = manager.location!.coordinate
    let objLocation = CLLocation(latitude: locValue.latitude, longitude: locValue.longitude)
    CLGeocoder().reverseGeocodeLocation(objLocation) { (placemarksArray, error) in
        if error != nil {
            print("Reverse geocoder failed with error" + (error?.localizedDescription)!)
            return
        }
        if (placemarksArray?.count)! > 0 {
            let objPlacemark = placemarksArray?[0]
            self.generateAddress(objPlacemark: objPlacemark!)
            self.locationManager?.stopUpdatingLocation()
            self.locationManager = nil
        }
        else {
            print("Problem with the data received from geocoder")
        }
    }
}

Function Parsing placemark to string...

func generateAddress(objPlacemark : CLPlacemark) -> String {

    print("objPlacemark : \(objPlacemark.description)")
    var completeAddress = ""

    if objPlacemark.name != nil {
        completeAddress = String(describing: objPlacemark.name!)
    }

    if objPlacemark.thoroughfare != nil && (objPlacemark.name != objPlacemark.thoroughfare) {
        completeAddress = completeAddress + ", " + String(describing: objPlacemark.thoroughfare!)
    }

    if objPlacemark.subThoroughfare != nil {
        completeAddress = completeAddress + ", " + String(describing: objPlacemark.subThoroughfare!)
    }

    if objPlacemark.subLocality != nil {
        completeAddress = completeAddress + "," + String(describing: objPlacemark.subLocality!)
    }

    if objPlacemark.locality != nil {
        completeAddress = String(describing: objPlacemark.locality!)
    }

    if objPlacemark.postalCode != nil {
        completeAddress = completeAddress + "," + String(describing: objPlacemark.postalCode!)
    }

    if objPlacemark.administrativeArea != nil {
        completeAddress = completeAddress + "," +  String(describing: objPlacemark.administrativeArea!)
    }

    if objPlacemark.isoCountryCode != nil {
        completeAddress = completeAddress + "," + String(describing: objPlacemark.isoCountryCode!)
    }

    print("completeAddress : \(completeAddress)")
    return completeAddress
}
Vinaykrishnan
  • 740
  • 3
  • 14
  • 34
0

CLGeocodeCompletionHandler contains an array of CLPlacemark. You can access its properties such as name, locality, isoCountryCode etc to form a complete address!!

iOSer
  • 2,241
  • 1
  • 18
  • 26