Swift - 从反向地理编码生成地址格式

Din*_*uka 20 xcode google-maps reverse-geocoding ios swift

我试图使用Swift 3中的CLGeocoder生成格式化的完整地址.我引用了这个SO线程来获取下面给出的代码.

但是,有时应用程序崩溃时会出现"nil"错误:

//Address dictionary
print(placeMark.addressDictionary ?? "")
Run Code Online (Sandbox Code Playgroud)

问题:

  1. 如何连接从GeoCoder检索到的这些值以形成完整地址?(街+城+等)
  2. 当func无法找到地址时,如何处理我得到的nil错误?

完整代码:

func getAddress() -> String {
        var address: String = ""

        let geoCoder = CLGeocoder()
        let location = CLLocation(latitude: selectedLat, longitude: selectedLon)
        //selectedLat and selectedLon are double values set by the app in a previous process

        geoCoder.reverseGeocodeLocation(location, completionHandler: { (placemarks, error) -> Void in

            // Place details
            var placeMark: CLPlacemark!
            placeMark = placemarks?[0]

            // Address dictionary
            //print(placeMark.addressDictionary ?? "")

            // Location name
            if let locationName = placeMark.addressDictionary!["Name"] as? NSString {
                //print(locationName)
            }

            // Street address
            if let street = placeMark.addressDictionary!["Thoroughfare"] as? NSString {
                //print(street)
            }

            // City
            if let city = placeMark.addressDictionary!["City"] as? NSString {
                //print(city)
            }

            // Zip code
            if let zip = placeMark.addressDictionary!["ZIP"] as? NSString {
                //print(zip)
            }

            // Country
            if let country = placeMark.addressDictionary!["Country"] as? NSString {
                //print(country)
            }

        })

        return address;
    } 
Run Code Online (Sandbox Code Playgroud)

Him*_*iya 58

func getAddressFromLatLon(pdblLatitude: String, withLongitude pdblLongitude: String) {
        var center : CLLocationCoordinate2D = CLLocationCoordinate2D()
        let lat: Double = Double("\(pdblLatitude)")!
        //21.228124
        let lon: Double = Double("\(pdblLongitude)")!
        //72.833770
        let ceo: CLGeocoder = CLGeocoder()
        center.latitude = lat
        center.longitude = lon

        let loc: CLLocation = CLLocation(latitude:center.latitude, longitude: center.longitude)


        ceo.reverseGeocodeLocation(loc, completionHandler:
            {(placemarks, error) in
                if (error != nil)
                {
                    print("reverse geodcode fail: \(error!.localizedDescription)")
                }
                let pm = placemarks! as [CLPlacemark]

                if pm.count > 0 {
                    let pm = placemarks![0]
                    print(pm.country)
                    print(pm.locality)
                    print(pm.subLocality)
                    print(pm.thoroughfare)
                    print(pm.postalCode)
                    print(pm.subThoroughfare)
                    var addressString : String = ""
                    if pm.subLocality != nil {
                        addressString = addressString + pm.subLocality! + ", "
                    }
                    if pm.thoroughfare != nil {
                        addressString = addressString + pm.thoroughfare! + ", "
                    }
                    if pm.locality != nil {
                        addressString = addressString + pm.locality! + ", "
                    }
                    if pm.country != nil {
                        addressString = addressString + pm.country! + ", "
                    }
                    if pm.postalCode != nil {
                        addressString = addressString + pm.postalCode! + " "
                    }


                    print(addressString)
              }
        })

    }
Run Code Online (Sandbox Code Playgroud)

  • @HimanshuMoradiya:工作就像一个魅力,非常感谢,但有一点要提,你不应该强行打开**地标**,因为它可能有时会发生在我身上,使用一个如果让我摆脱不必要的崩溃.:P干杯.快乐的编码. (3认同)

Ger*_*tan 11

格式化地址很难,因为每个国家/地区都有自己的格式.让Apple这样做:

从iOS 11开始,您可以获得一个Contacts框架地址:

extension CLPlacemark {
    @available(iOS 11.0, *)
    open var postalAddress: CNPostalAddress? { get }
}
Run Code Online (Sandbox Code Playgroud)

此扩展是Contacts框架的一部分.这意味着,在您XCode完成代码完成之前,此功能对您来说是不可见的

import Contacts
Run Code Online (Sandbox Code Playgroud)

通过这个额外的导入,你可以做类似的事情

CLGeocoder().reverseGeocodeLocation(location, preferredLocale: nil) { (clPlacemark: [CLPlacemark]?, error: Error?) in
    guard let place = clPlacemark?.first else {
        print("No placemark from Apple: \(String(describing: error))")
        return
    }

    let postalAddressFormatter = CNPostalAddressFormatter()
    postalAddressFormatter.style = .mailingAddress
    var addressString: String?
    if let postalAddress = place.postalAddress {
        addressString = postalAddressFormatter.string(from: postalAddress)
    }
}
Run Code Online (Sandbox Code Playgroud)

并获取地址中国家/地区格式的格式.

格式化程序甚至支持格式化为attributionString.

在iOS 11之前,您可以转换CLPlacemarkCNPostalAddress自己,仍然可以使用特定于国家/地区的格式CNPostalAddressFormatter.

  • 救生员。谢谢您的帮助。 (2认同)

Mid*_* MP 6

  1. 为了解决空地址问题,您可以使用类属性来保存附加值,也可以使用闭包将值返回给调用函数
  2. 为了修复崩溃,您需要避免强制展开选项

使用闭包你可以这样做:

// Using closure
func getAddress(handler: @escaping (String) -> Void)
{
    var address: String = ""
    let geoCoder = CLGeocoder()
    let location = CLLocation(latitude: selectedLat, longitude: selectedLon)
    //selectedLat and selectedLon are double values set by the app in a previous process
    
    geoCoder.reverseGeocodeLocation(location, completionHandler: { (placemarks, error) -> Void in
        
        // Place details
        var placeMark: CLPlacemark?
        placeMark = placemarks?[0]
        
        // Address dictionary
        //print(placeMark.addressDictionary ?? "")
        
        // Location name
        if let locationName = placeMark?.addressDictionary?["Name"] as? String {
            address += locationName + ", "
        }
        
        // Street address
        if let street = placeMark?.addressDictionary?["Thoroughfare"] as? String {
            address += street + ", "
        }
        
        // City
        if let city = placeMark?.addressDictionary?["City"] as? String {
            address += city + ", "
        }
        
        // Zip code
        if let zip = placeMark?.addressDictionary?["ZIP"] as? String {
            address += zip + ", "
        }
        
        // Country
        if let country = placeMark?.addressDictionary?["Country"] as? String {
            address += country
        }
        
       // Passing address back
       handler(address)
    })
}
Run Code Online (Sandbox Code Playgroud)

您可以像这样调用该方法:

getAddress { (address) in
    print(address)
}
Run Code Online (Sandbox Code Playgroud)


osc*_*lon 6

这是我的swift 3代码

func getAdressName(coords: CLLocation) {

    CLGeocoder().reverseGeocodeLocation(coords) { (placemark, error) in
            if error != nil {
                print("Hay un error")
            } else {

                let place = placemark! as [CLPlacemark]
                if place.count > 0 {
                    let place = placemark![0]
                    var adressString : String = ""
                    if place.thoroughfare != nil {
                        adressString = adressString + place.thoroughfare! + ", "
                    }
                    if place.subThoroughfare != nil {
                        adressString = adressString + place.subThoroughfare! + "\n"
                    }
                    if place.locality != nil {
                        adressString = adressString + place.locality! + " - "
                    }
                    if place.postalCode != nil {
                        adressString = adressString + place.postalCode! + "\n"
                    }
                    if place.subAdministrativeArea != nil {
                        adressString = adressString + place.subAdministrativeArea! + " - "
                    }
                    if place.country != nil {
                        adressString = adressString + place.country!
                    }

                    self.lblPlace.text = adressString
                }
            }
        }
  }
Run Code Online (Sandbox Code Playgroud)

您可以按照以下方式调用以上功能:

let cityCoords = CLLocation(latitude: newLat, longitude: newLon)
cityData(coord: cityCoords)
Run Code Online (Sandbox Code Playgroud)