如何使用 geocodeAddressString 将多个 MKAnnotation 添加到地图?

问题描述 投票:0回答:1

我开始在 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)
        
        
    }
}

显然,由于函数是异步的,因此该代码的行为不是我所期望的(仅添加了第一个城市)。我想这可以通过闭包来完成,但我不确定如何实现。如有任何帮助,我们将不胜感激!

  • 我已阅读Apple的文档
  • 我尝试将 @escaping 与闭包一起添加,但没有成功
  • 为了让它发挥作用,我编写了一个递归函数,它将添加到一个城市的注释数组中,然后它会为下一个城市再次调用自身(存储在城市数组中)
ios swift iphone mapkit
1个回答
0
投票

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")
}
© www.soinside.com 2019 - 2024. All rights reserved.