【问题标题】:How to wait until CLGeocoder finish its work如何等到 CLGeocoder 完成工作
【发布时间】: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

标签: swift clgeocoder


【解决方案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。它现在可以完美运行了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-16
    • 1970-01-01
    • 2021-10-27
    • 1970-01-01
    • 2019-05-11
    • 2016-06-17
    相关资源
    最近更新 更多