简体   繁体   English

在循环中使用 async/await 的问题 | Swift

[英]Issue using async/await in loop | Swift

Essentially I am converting string addresses into CLLocationCoordinate2D, to acheive this I am looping through an array of addresses that are in a specific order I need to keep the same, but when the escaping async function runs it changes the order of the array addresses as a result, how can async/await be used to achieve this result?本质上,我将字符串地址转换为 CLLocationCoordinate2D,为了实现这一点,我正在循环按特定顺序的地址数组,我需要保持不变,但是当 escaping 异步 function 运行时,它会将数组地址的顺序更改为结果,如何使用 async/await 来达到这个结果?

Resources like this are helpful but I am still struggling to understand the proper way to implement.像这样的资源很有帮助,但我仍在努力理解正确的实施方式。 https://www.biteinteractive.com/swift-5-5-asynchronous-looping-with-async-await/ https://www.biteinteractive.com/swift-5-5-asynchronous-looping-with-async-await/

func getLocation(from address: String, completion: @escaping (_ location: CLLocationCoordinate2D?)-> Void) {
    let geocoder = CLGeocoder()
    geocoder.geocodeAddressString(address) { (placemarks, error) in
        guard let placemarks = placemarks,
              let location = placemarks.first?.location?.coordinate
        else {
            completion(nil)
            return
        }
        completion(location)
    }
}

let addresses = ["SAUGET, IL", "SAN FRANCISCO, CA", "SAINT LOUIS, MO"]

for address in addresses {
    print(address)
    getLocation(from: address) { location in
        
        //printing not the same order as the order the loop is sending them in.
        print("address: \(address)")
    }
}

Just make an rendition that uses the async-await rendition of geocodeAddressString :只需制作一个使用geocodeAddressString的异步等待再现的再现:

func getCoordinate(from address: String) async throws -> CLLocationCoordinate2D {
    let geocoder = CLGeocoder()

    guard let location = try await geocoder.geocodeAddressString(address)
        .compactMap( { $0.location } )
        .first(where: { $0.horizontalAccuracy >= 0 } )
    else {
        throw CLError(.geocodeFoundNoResult)
    }

    return location.coordinate
}

Then you can do:然后你可以这样做:

func lookupCoordinates() async throws {
    let addresses = ["SAUGET, IL", "SAN FRANCISCO, CA", "SAINT LOUIS, MO", "NEW YORK, NY"]
    
    for address in addresses {
        let coordinate = try await getCoordinate(from: address)
        print("address: \(coordinate)")
    }
}

Unrelated, we should note that the geocodeAddressString documentation warns us:无关,我们应该注意到geocodeAddressString 文档警告我们:

After initiating a forward-geocoding request, do not attempt to initiate another reverse- or forward-geocoding request.发起前向地理编码请求后,不要尝试发起另一个反向或前向地理编码请求。

The CLGeocoder documentation also warns us: CLGeocoder 文档还警告我们:

Geocoding requests are rate-limited for each app, so making too many requests in a short period of time may cause some of the requests to fail.每个应用程序的地理编码请求都有速率限制,因此在短时间内发出过多请求可能会导致某些请求失败。 ... Send at most one geocoding request for any one user action. ... 最多为任何一项用户操作发送一个地理编码请求。

Just a FYI.仅供参考。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM