如何等到 CLGeocoder 完成工作

Posted

技术标签:

【中文标题】如何等到 CLGeocoder 完成工作【英文标题】:How to wait until CLGeocoder finish its work 【发布时间】:2021-08-30 19:51:01 【问题描述】:

我有以下来自 GPS 坐标的功能地理编码地址

private func getAddressFromLocation(forLocation: CLLocationCoordinate2D) 
    let geoCoder = CLGeocoder()
    geoCoder.reverseGeocodeLocation(CLLocation(latitude: forLocation.latitude, longitude: forLocation.longitude), completionHandler: (places, error) in
        guard error == nil else 
            return
        
        let place: CLPlacemark = places!.first!
        var address: [String] = []
        if place.country != nil  address.append(place.country!) 
        if place.postalCode != nil  address.append(place.postalCode!) 
        if place.locality != nil  address.append(place.locality!) 
        if place.thoroughfare != nil  address.append(place.thoroughfare!) 
        self.fullAddress = address.joined(separator: ",")
    )

从我的应用程序的另一部分调用函数,我想知道如何确保程序将等到 fullAddress 变量获得值(函数完成)。我试图将函数调用放入同步调度队列,但没有帮助。 感谢您的任何建议。

【问题讨论】:

不要问,要告诉。意思是:不要等待,通知。请搜索completion handler 【参考方案1】:

我愿意:

使用Result 类型的完成处理程序; 将 UI 更新与反向地理编码解耦; 使用Contacts框架中的CNPostalAddressFormatter来格式化地址;

例如


enum GeocodeError: Error 
    case notFound


let geocoder = CLGeocoder()

func getAddress(for coordinate: CLLocationCoordinate2D, completion: @escaping (Result<String, Error>) -> Void) 
    let location = CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude)
    geocoder.reverseGeocodeLocation(location)  places, error in
        guard error == nil, let address = places?.first?.postalAddress else 
            completion(.failure(error ?? GeocodeError.notFound))
            return
        

        let formatter = CNPostalAddressFormatter()
        let string = formatter.string(from: address)
            .components(separatedBy: "\n")
            .joined(separator: ", ")
        completion(.success(string))
    

然后这样称呼它:

getAddress(for: coordinate)  result in
    switch result 
    case .failure(let error):   // update UI to report error, if any
    case .success(let address): // update UI to show address
    

【讨论】:

【参考方案2】:

是的,完成处理程序将成为您的朋友:

typealias CompletionHandler = (_ success:Bool) -> Void

private func getAddressFromLocation(forLocation: CLLocationCoordinate2D, completionHandler: @escaping CompletionHandler) 
    let geoCoder = CLGeocoder()
    geoCoder.reverseGeocodeLocation(CLLocation(latitude: forLocation.latitude, longitude: forLocation.longitude), completionHandler: (places, error) in
        guard error == nil else 
            completionHandler(false)
            return
        
        let place: CLPlacemark = places!.first!
        var address: [String] = []
        if place.country != nil  address.append(place.country!) 
        if place.postalCode != nil  address.append(place.postalCode!) 
        if place.locality != nil  address.append(place.locality!) 
        if place.thoroughfare != nil  address.append(place.thoroughfare!) 
        print("address: \(address.joined(separator: ","))")
        completionHandler(true)
    )

你可以这样称呼它:

getAddressFromLocation(forLocation: CLLocationCoordinate2D())  success in
    if success 
        //once address is fetched, this will be triggered.
    

【讨论】:

谢谢你,Brendan C。它现在可以完美运行了。

以上是关于如何等到 CLGeocoder 完成工作的主要内容,如果未能解决你的问题,请参考以下文章

如何让python脚本等到下载完成

CLGeocoder 延迟直到完成处理程序

如何让函数等到动画完成?

CLGeocoder 不工作

使用 CLGeocoder 的正向地理编码示例

CLGeocoder 可以在美国以外的全球范围内工作吗?