Swift 4中的反向地理编码 [英] Reverse geocoding in Swift 4
问题描述
我正在尝试编写一种简单的方法,该方法可以填充 CLLocationDegrees
并返回 CLPlacemark
。查看 Apple的文档,这似乎很简单。 p>
以下是我扔到操场上的东西:
import CoreLocation
//这对于游乐场中的异步代码是必需的
import PlaygroundSupport
//这对于游乐场中的异步代码是必需的
PlaygroundPage.current.needsIndefiniteExecution = true
功能地理编码(纬度:CLLocationDegrees,经度:CLLocationDegrees)-> CLPlacemark? {
let location = CLLocation(纬度:纬度,经度:经度)
let geocoder = CLGeocoder()
var地标:CLPlacemark?
geocoder.reverseGeocodeLocation(location){(地标,错误)在
中,如果出现错误!= nil {
print(发生了严重错误)
} $如果让地标=地标{
地标=地标,则
.first
}
}
返回地标
}
让myPlacemark =地理编码(纬度:37.3318,经度:122.0312)
,我的方法返回nil。我不确定我的错误在哪里,但我可以放心,这对我来说是愚蠢的。谢谢您的阅读。
import UIKit
import CoreLocation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
func地理编码(纬度:双倍,经度:双倍,完成:@转义(_地标:[CLPlacemark]?,_错误:错误?)->无效){
CLGeocoder()。reverseGeocodeLocation(CLLocation(纬度:纬度,经度:经度)){地标,
中的错误警卫队让地标=地标,错误==零,否则{
完成(零,错误)
返回
}
完成(地标,无)
}
}
或简单地:
func地理编码(纬度:Double,经度:Double,完成度: @转义(_地标:[CLPlacemark]?,_错误:错误?)->无效){
CLGeocoder()。reverseGeocodeLocation(CLLocation(latitude:latitud e,经度:longitude),completionHandler:完成)
}
或扩展CLLocation:
扩展名CLLocation {
func geocode(完成:@转义(_地标:[CLPlacemark]?,_错误:错误?)->无效){
CLGeocoder()。reverseGeocodeLocation(self,completeHandler:完成)
}
}
要将地标格式化为邮件地址,可以使用联系人框架 CNPostalAddressFormatter
:
import联系人
扩展Formatter {
static let mailingAddress:CNPostalAddressFormatter = {
let formatter = CNPostalAddressFormatter()
formatter.style = .mailingAddress
返回格式化程序
}()
}
扩展CLPlacemark {
var mailingAddress:字符串? {
return postalAddress?.mailingAddress
}
}
扩展名CNPostalAddress {
var mailingAddress:字符串{
return Formatter.mailingAddress.string (来自:自我)
}
}
地标
包含一组CLPlacemark对象。对于大多数地理编码请求,此数组
只能包含一个条目。但是,在
指定地址无法解析到单个位置的情况下,前向地理编码
请求可能返回多个地标对象。如果
请求被取消或获取地标
信息时出错,则此参数为nil。
有关CLPlacemark属性的更多信息,可以检查此 CLPlacemark
用法:
让位置= CLLocation(纬度:-22.963451,经度:-43.198242)
location.geocode {地标,如果让error = error as,则
中存在错误? CLError {
print( CLError:,error)
return
}否则,如果let placemark = placemark?.first {
//您应该始终在主界面中更新UI线程
DispatchQueue.main.async {
//在此处更新UI
print( name:,placemark.name ?? unknown)
print( address1:,placemark.thoroughfare ??未知)
print( address2:,placemark.subThoroughfare ?? unknown)
print( neighborhood:,placemark.subLocality ?? 未知)
print( city:,placemark.locality ??未知)
print( state:,placemark.administrativeArea ??未知)
print( subAdministrativeArea:,placemark.subAdministrativeArea ??未知)
print(邮政编码:,placemark.postalCode ??未知)
print( country:, placemark.country ?? unknown,终止符: \n\n)
print( isoCountry代码:,placemark.isoCountryCode? unknown)
print( region identifier:,placemark.region?.identifier ?? unknown)
print( timezone:,placemark.timeZone ?? unknown ,终止符: \n\n)
// Mailind地址
print(placemark.mailingAddress ??未知)
}
}
}
这将打印
名称:Morro da Saudade
地址1:Rua Casuarina
地址2:597
社区:Lagoa
城市:Rio de Janeiro
省:RJ
subAdministrativeArea:不明
邮政编码:22011-040
国家:巴西
isoCountryCode:BR
区域标识符:< -22.96345100,-43.19824200>半径141.83
时区:America / Sao_Paulo(当前)
Rua Casuarina,597
拉各斯
里约热内卢RJ
22011-040
巴西
I'm attempting to write a simple method that's fed CLLocationDegrees
and returns a CLPlacemark
. Looking at Apple's documentation, it seems like a simple task.
Below is what I've dumped into a playground:
import CoreLocation
// this is necessary for async code in a playground
import PlaygroundSupport
// this is necessary for async code in a playground
PlaygroundPage.current.needsIndefiniteExecution = true
func geocode(latitude: CLLocationDegrees, longitude: CLLocationDegrees) -> CLPlacemark? {
let location = CLLocation(latitude: latitude, longitude: longitude)
let geocoder = CLGeocoder()
var placemark: CLPlacemark?
geocoder.reverseGeocodeLocation(location) { (placemarks, error) in
if error != nil {
print("something went horribly wrong")
}
if let placemarks = placemarks {
placemark = placemarks.first
}
}
return placemark
}
let myPlacemark = geocode(latitude: 37.3318, longitude: 122.0312)
As it stands, my method is returning nil. I'm not sure where my error lies, but I rest assured it's something starlingly stupid on my part. Thank you for reading.
import UIKit
import CoreLocation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
func geocode(latitude: Double, longitude: Double, completion: @escaping (_ placemark: [CLPlacemark]?, _ error: Error?) -> Void) {
CLGeocoder().reverseGeocodeLocation(CLLocation(latitude: latitude, longitude: longitude)) { placemark, error in
guard let placemark = placemark, error == nil else {
completion(nil, error)
return
}
completion(placemark, nil)
}
}
or simply:
func geocode(latitude: Double, longitude: Double, completion: @escaping (_ placemark: [CLPlacemark]?, _ error: Error?) -> Void) {
CLGeocoder().reverseGeocodeLocation(CLLocation(latitude: latitude, longitude: longitude), completionHandler: completion)
}
or extending CLLocation:
extension CLLocation {
func geocode(completion: @escaping (_ placemark: [CLPlacemark]?, _ error: Error?) -> Void) {
CLGeocoder().reverseGeocodeLocation(self, completionHandler: completion)
}
}
To format your place mark as a mailing address you can use Contacts framework CNPostalAddressFormatter
:
import Contacts
extension Formatter {
static let mailingAddress: CNPostalAddressFormatter = {
let formatter = CNPostalAddressFormatter()
formatter.style = .mailingAddress
return formatter
}()
}
extension CLPlacemark {
var mailingAddress: String? {
return postalAddress?.mailingAddress
}
}
extension CNPostalAddress {
var mailingAddress: String {
return Formatter.mailingAddress.string(from: self)
}
}
placemark
Contains an array of CLPlacemark objects. For most geocoding requests, this array should contain only one entry. However, forward-geocoding requests may return multiple placemark objects in situations where the specified address could not be resolved to a single location. If the request was canceled or there was an error in obtaining the placemark information, this parameter is nil.
For more information about the CLPlacemark properties you can check this CLPlacemark
Usage:
let location = CLLocation(latitude: -22.963451, longitude: -43.198242)
location.geocode { placemark, error in
if let error = error as? CLError {
print("CLError:", error)
return
} else if let placemark = placemark?.first {
// you should always update your UI in the main thread
DispatchQueue.main.async {
// update UI here
print("name:", placemark.name ?? "unknown")
print("address1:", placemark.thoroughfare ?? "unknown")
print("address2:", placemark.subThoroughfare ?? "unknown")
print("neighborhood:", placemark.subLocality ?? "unknown")
print("city:", placemark.locality ?? "unknown")
print("state:", placemark.administrativeArea ?? "unknown")
print("subAdministrativeArea:", placemark.subAdministrativeArea ?? "unknown")
print("zip code:", placemark.postalCode ?? "unknown")
print("country:", placemark.country ?? "unknown", terminator: "\n\n")
print("isoCountryCode:", placemark.isoCountryCode ?? "unknown")
print("region identifier:", placemark.region?.identifier ?? "unknown")
print("timezone:", placemark.timeZone ?? "unknown", terminator:"\n\n")
// Mailind Address
print(placemark.mailingAddress ?? "unknown")
}
}
}
This will print
name: Morro da Saudade
address1: Rua Casuarina
address2: 597
neighborhood: Lagoa
city: Rio de Janeiro
state: RJ
subAdministrativeArea: unknown
zip code: 22011-040
country: Brazil
isoCountryCode: BR
region identifier: <-22.96345100,-43.19824200> radius 141.83
timezone: America/Sao_Paulo (current)
Rua Casuarina, 597
Lagoa
Rio de Janeiro RJ
22011-040
Brazil
这篇关于Swift 4中的反向地理编码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!