2016-12-28 151 views
1

我試圖在Swift 8中使用CLGeocoder生成格式化完整地址。我參考了SO線程獲取下面給出的代碼。Swift - 從反向地理編碼生成地址格式

但是,有時應用程序崩潰,在該行一個「零」的錯誤:

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

問題:

  1. 我如何可以連接地址解析器中檢索這些值來形成完整地址? (街道+城市+等)
  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; 
    } 

回答

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

    } 
+0

和最後的打印地址字符串。你有你的整個地址 –

+0

有這個問題。在等待地址從LatLng處理之前,func經歷這個過程。因此,我最終得到一個空字符串 – Dinuka

+1

@RickGrimesLikesWalkerSoup檢查我在我的項目中使用的整個方法。你也可以使用它 –

2

要連接,你可以簡單地通過這個替換return address

return "\(locationName), \(street), \(city), \(zip), \(country)" 
+0

這不提供問題的答案。要批評或要求作者澄清,請在其帖子下方留言。 - [來自評論](/ review/low-quality-posts/14721054) – Mayur

+0

@Mack對「如何連接...」的回答 – Makaille

+0

可能您應該添加一些關於該怎麼做,如何使用,使用這條線和一些東西。現在只需簡單地放置1行並不總是得到適當的解決方案。 – Mayur

1
  1. 爲了固定空地址問題,或者你可以使用類屬性來保存附加值,或者您可以使用一個封閉返回值返回給調用函數
  2. 爲了固定崩潰你需要避免力自選

的展開使用閉包,你可以不喜歡它:

// Using closure 
func getAddress(handler: (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) 
    }) 
} 

你可以調用像方法:

getAddress { (address) in 
    print(address) 
} 
2

這是我的代碼4 SWIFT 3

func getAdressName(coords: CLLocation) { 

    CLGeocoder().reverseGeocodeLocation(location) { (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 
       } 

      } 
     } 
    } 

可以調用,如:

let cityCoords = CLLocation(latitude: newLat, longitude: newLon) 
cityData(coord: cityCoords) 
0

保持簡單 - 一個完整的斯威夫特3 & 4兼容視圖控制器例如從用戶的位置獲得一個格式化的地址字符串(以可用的其他鍵加入CLPlacemark如果你想在你的字符串的詳細信息):

import UIKit 
import CoreLocation 

class ViewController: UIViewController, CLLocationManagerDelegate { 

let manager = CLLocationManager() 
let geocoder = CLGeocoder() 

var locality = "" 
var administrativeArea = "" 
var country = "" 

override func viewDidLoad() { 
    super.viewDidLoad() 

    manager.delegate = self 
    manager.desiredAccuracy = kCLLocationAccuracyBest 
    manager.requestWhenInUseAuthorization() 
    manager.startUpdatingLocation() 

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { 
     let location = locations[0] 
     manager.stopUpdatingLocation() 

    geocoder.reverseGeocodeLocation(location, completionHandler: {(placemarks, error) in 
     if (error != nil) { 
      print("Error in reverseGeocode") 
      } 

     let placemark = placemarks! as [CLPlacemark] 
     if placemark.count > 0 { 
      let placemark = placemarks![0] 
      self.locality = placemark.locality! 
      self.administrativeArea = placemark.administrativeArea! 
      self.country = placemark.country! 
     } 
    }) 
} 

func userLocationString() -> String { 
    let userLocationString = "\(locality), \(administrativeArea), \(country)" 
    return userLocationString 
} 

} 

調用印刷(userLocationString())在這個例子中會打印:郊區,州,國家

不要忘了添加隱私 - 使用時的位置使用說明事先添加到您的Info.plist文件,以允許用戶授予您的應用程序使用位置服務的權限。