Swift:用于地理编码的递归异步循环
Swift: Asynchronous Loop with Recursion for GeoCoding
一次只能发生一个 GeoCode 请求,而且它们是异步的,所以我需要在前一个完成后立即开始下一个。我让它像这样工作:
func one() {
let geocoder = CLGeocoder()
let one = myPlacesFakeData[0]
geocoder.geocodeAddressString(one.address, completionHandler: { (placemarks, error) in
if let error = error {
print("Unable to Reverse Geocode Location (\(error))")
} else {
if let placemarks = placemarks, let placemark = placemarks.first {
myPlacesFakeData[0].latitude = placemark.location?.coordinate.latitude
myPlacesFakeData[0].longitude = placemark.location?.coordinate.longitude
} else {
print("No Matching Address Found")
}
}
self.two()
})
}
func two() {
let geocoder = CLGeocoder()
let two = myPlacesFakeData[1]
geocoder.geocodeAddressString(two.address, completionHandler: { (placemarks, error) in
if let error = error {
print("Unable to Reverse Geocode Location (\(error))")
} else {
if let placemarks = placemarks, let placemark = placemarks.first {
myPlacesFakeData[1].latitude = placemark.location?.coordinate.latitude
myPlacesFakeData[1].longitude = placemark.location?.coordinate.longitude
} else {
print("No Matching Address Found")
}
}
self.three()
})
}
func three() {
let geocoder = CLGeocoder()
let three = myPlacesFakeData[2]
geocoder.geocodeAddressString(three.address, completionHandler: { (placemarks, error) in
if let error = error {
print("Unable to Reverse Geocode Location (\(error))")
} else {
if let placemarks = placemarks, let placemark = placemarks.first {
myPlacesFakeData[2].latitude = placemark.location?.coordinate.latitude
myPlacesFakeData[2].longitude = placemark.location?.coordinate.longitude
} else {
print("No Matching Address Found")
}
}
})
}
但这是贫民窟,取决于我尝试地理编码的恰好三个地方。
我想我需要一个递归函数和一个计数器,但我不确定如何写这个。任何帮助将不胜感激。
这是展示一种方法的游乐场。您可以使用一个函数,该函数将调用自身并累积结果,一旦所有地址都经过地理编码,该函数最终将调用完成处理程序。您可以通过错误处理和更好的类型包装来做得更好,但这是一个很好的起点!
//: Playground - noun: a place where people can play
import Cocoa
import CoreLocation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
func geoCode(addresses: [String], results: [CLPlacemark] = [], completion: @escaping ([CLPlacemark]) -> Void ) {
guard let address = addresses.first else {
completion(results)
return
}
let geoCoder = CLGeocoder()
geoCoder.geocodeAddressString(address) { placemarks, error in
var updatedResults = results
if let placemark = placemarks?.first {
updatedResults.append(placemark)
}
let remainingAddresses = Array(addresses[1..<addresses.count])
geoCode(addresses: remainingAddresses, results: updatedResults, completion: completion)
}
}
let addresses = ["1600 Pennsylvania Ave NW, Washington, DC 20500", "1 Infinite Loop, Cupertino, CA"]
geoCode(addresses: addresses) { results in
print("Got back \(results.count) results")
}
一次只能发生一个 GeoCode 请求,而且它们是异步的,所以我需要在前一个完成后立即开始下一个。我让它像这样工作:
func one() {
let geocoder = CLGeocoder()
let one = myPlacesFakeData[0]
geocoder.geocodeAddressString(one.address, completionHandler: { (placemarks, error) in
if let error = error {
print("Unable to Reverse Geocode Location (\(error))")
} else {
if let placemarks = placemarks, let placemark = placemarks.first {
myPlacesFakeData[0].latitude = placemark.location?.coordinate.latitude
myPlacesFakeData[0].longitude = placemark.location?.coordinate.longitude
} else {
print("No Matching Address Found")
}
}
self.two()
})
}
func two() {
let geocoder = CLGeocoder()
let two = myPlacesFakeData[1]
geocoder.geocodeAddressString(two.address, completionHandler: { (placemarks, error) in
if let error = error {
print("Unable to Reverse Geocode Location (\(error))")
} else {
if let placemarks = placemarks, let placemark = placemarks.first {
myPlacesFakeData[1].latitude = placemark.location?.coordinate.latitude
myPlacesFakeData[1].longitude = placemark.location?.coordinate.longitude
} else {
print("No Matching Address Found")
}
}
self.three()
})
}
func three() {
let geocoder = CLGeocoder()
let three = myPlacesFakeData[2]
geocoder.geocodeAddressString(three.address, completionHandler: { (placemarks, error) in
if let error = error {
print("Unable to Reverse Geocode Location (\(error))")
} else {
if let placemarks = placemarks, let placemark = placemarks.first {
myPlacesFakeData[2].latitude = placemark.location?.coordinate.latitude
myPlacesFakeData[2].longitude = placemark.location?.coordinate.longitude
} else {
print("No Matching Address Found")
}
}
})
}
但这是贫民窟,取决于我尝试地理编码的恰好三个地方。
我想我需要一个递归函数和一个计数器,但我不确定如何写这个。任何帮助将不胜感激。
这是展示一种方法的游乐场。您可以使用一个函数,该函数将调用自身并累积结果,一旦所有地址都经过地理编码,该函数最终将调用完成处理程序。您可以通过错误处理和更好的类型包装来做得更好,但这是一个很好的起点!
//: Playground - noun: a place where people can play
import Cocoa
import CoreLocation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
func geoCode(addresses: [String], results: [CLPlacemark] = [], completion: @escaping ([CLPlacemark]) -> Void ) {
guard let address = addresses.first else {
completion(results)
return
}
let geoCoder = CLGeocoder()
geoCoder.geocodeAddressString(address) { placemarks, error in
var updatedResults = results
if let placemark = placemarks?.first {
updatedResults.append(placemark)
}
let remainingAddresses = Array(addresses[1..<addresses.count])
geoCode(addresses: remainingAddresses, results: updatedResults, completion: completion)
}
}
let addresses = ["1600 Pennsylvania Ave NW, Washington, DC 20500", "1 Infinite Loop, Cupertino, CA"]
geoCode(addresses: addresses) { results in
print("Got back \(results.count) results")
}