我开始在 Swift 上编程,并且我已经构建了几个简单的应用程序。
我希望在我的应用程序中有一个使用 MKAnnotation 显示两个城市(或更多)的视图。我看到 CLGeocoder 中有一个名为 geocodeAddressString() 的函数。我发现这个功能非常有用,因为我不需要知道任何地方的坐标来进行注释:我只需写下城市,它就会出现在地图中。
我已经在谷歌上搜索过,有一些带有坐标的解决方案,但特别不是带有 geocodeAddressString() 的解决方案。我读过苹果的文档,看起来它是一个异步函数。我的代码如下:
import UIKit
import MapKit
class ViewController: UIViewController {
@IBOutlet var map: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
setUpMap()
}
func setUpMap(){
var points: [MKPointAnnotation] = []
let geoCoder = CLGeocoder()
geoCoder.geocodeAddressString("Paris, France", completionHandler: { placemarks, error in
let annotation = MKPointAnnotation()
if let location = placemarks?.first?.location {
annotation.coordinate = location.coordinate
points.append(annotation)
}
})
geoCoder.geocodeAddressString("Sophia, Bulgaria", completionHandler: { placemarks, error in
let annotation = MKPointAnnotation()
if let location = placemarks?.first?.location {
annotation.coordinate = location.coordinate
points.append(annotation)
}
})
self.map.addAnnotations(points)
}
}
显然,由于函数是异步的,因此该代码的行为不是我所期望的(仅添加了第一个城市)。我想这可以通过闭包来完成,但我不确定如何实现。如有任何帮助,我们将不胜感激!
CLGeocoder
的文档说:
对任何一项用户操作最多发送一个地理编码请求。
为了一次只发送一个请求,我们可以利用 async/await。代码可能如下所示:
func setUpMap(){
Task { @MainActor [weak self] in
let geoCoder = CLGeocoder()
do {
let req1: [CLPlacemark] = try await geoCoder.geocodeAddressString("Paris, France")
if let location = req1.first?.location {
let annotation = MKPointAnnotation()
annotation.coordinate = location.coordinate
self?.map.addAnnotation(annotation)
}
let req2: [CLPlacemark] = try await geoCoder.geocodeAddressString("Sophia, Bulgaria")
if let location = req2.first?.location {
let annotation = MKPointAnnotation()
annotation.coordinate = location.coordinate
self?.map.addAnnotation(annotation)
}
} catch {
// handle errors
}
}
}
另一种解决方案是使用多个
CLGeocoder
:
func launchRequest(_ address: String) {
Task { @MainActor [weak self] in
do {
let geoCoder = CLGeocoder()
let req: [CLPlacemark] = try await geoCoder.geocodeAddressString(address)
if let location = req.first?.location {
let annotation = MKPointAnnotation()
annotation.coordinate = location.coordinate
self?.map.addAnnotation(annotation)
print("Annotation: ", annotation, location.coordinate)
}
} catch {
// handle error
}
}
}
func setUpMap(){
launchRequest("Paris, France")
launchRequest("Sophia, Bulgaria")
}