ios - 如何等待函数快速完成
问题描述
我有这个功能,我将用户的取货和送货地址转换为坐标。将地址转换为坐标后,我想计算它们的距离。我使用 REST api 转换和计算这些。
这些是我获得坐标的功能
if let url = URL(string: "APIURL"){
let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) { (data, resp, err) in
if err != nil{
print("Error converting adress to coordinates: \(err)")
}
if let safeData = data{
self.parseJSON(with: safeData, adressType: "From")
}
}
task.resume()
}
if let url = URL(string: "APIURL"){
let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) { (data, resp, err) in
if err != nil{
print("Error converting adress to coordinates: \(err)")
}
if let safeData = data{
self.parseJSON(with: safeData, adressType: "To")
}
}
task.resume()
}
所以我想要的是让这两个完成。在我得到这些值之后,我想计算距离。
这是距离请求
if let url = URL(string:"APIURL"){
let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) { (data, res, err) in
if err != nil{
print("Could not start task to fetch distance")
}
if let safeData = data{
self.parseDistanceJSON(with: safeData)
}
}
task.resume()
}
目前,它们都驻留在这一功能中
func fetchDistance(fromAdress: String, toAdress: String){
if let url = URL(string: "APIURL"){
// Fetch for fromAdress...
}
if let url = URL(string: "APIURL"){
// Fetch for toAdress...
}
if let url = URL(string: "APIURL"){
// Fetch for distance between fromAdress and toAdress...
}
}
唯一的问题是我希望它们按照您在代码中看到的确切顺序执行。但现在,这不是我能控制的。有时最后一次提取会先执行,有时它们会同时执行。
解决方案
您的第三个功能取决于前两个的数据,但前两个是独立的。
DispatchGroup
前两个完成后,您可以使用 a来执行第三个函数。前两个函数按什么顺序完成并不重要。
您确实需要考虑一个或多个网络操作可能会失败。
由于这些网络操作是异步的,因此您需要将完成处理程序传递给fetchDistance
并在工作完成时调用它。
就像是
enum MyError: Error {
case locationNotFound
}
func fetchDistance(fromAdress: String, toAdress: String, completion: @escaping (Result<Double, Error>) -> Void) {
var firstLocation: CLCoordinate2D?
var secondLocation: CLLocationCoordinate2D?
var error: Error?
let dispatchGroup = DispatchGroup()
dispatchGroup.enter();
self.fetchLocation(for: fromAddress) { result in
switch result {
case .failure(let operationError):
operationError = operationError;
case .success(let location):
firstLocation = location
}
dispatchGroup.leave()
}
dispatchGroup.enter();
self.fetchLocation(for: toAddress) { result in
switch result {
case .failure(let operationError):
operationError = operationError;
case .success(let location):
secondLocation = location
}
dispatchGroup.leave()
}
dispatchGroup.notify() {
guard error != nil else {
completion(.failure(error))
return
}
guard let first = firstLocation, let second = secondLocation else {
completion(.failure(MyError.locationNotFound)
return
}
self.findDistance(from: first, to: second) { result in
completion(result)
}
}
}
func fetchLocation(for address: string, completion: completion: @escaping (Result<CLLocationCoordinate2D, Error>) -> Void) {
// Perform API call to get lat & Lon for address.
// Convert lat & lon to CLLocationCoordinate2D
// Invoke completion
/// completion(.success(location))
}
func findDistance(from: CLLocationCoordinate2D, to: CLLocationCoordinate2D ,completion: completion: @escaping (Result<CLLocationCoordinate2D, Error>) -> Void) {
// Perform API call to get distance as double
// Invoke completion
/// completion(.success(distance))
}
推荐阅读
- html - 我找不到使用 jQuery 的特定元素
- java - 使用素数java打印算术级数
- redis - 我可以这样使用nestjs缓存服务吗?
- kotlin - 避免使用多态性(或设计模式)进行强制转换
- apache-superset - 如何连接 Apache Druid 和 Apache Superset
- reactjs - Semantic UI Dropdown ,尝试将状态从子级设置为父级
- javascript - 在 react-select 中的选项末尾附加一个按钮
- java - SonarQube 安全热点,使用正则表达式
- video-streaming - 为什么流媒体下载器无法从某些流媒体网站下载?
- flutter - Flutter:如何在 google_maps_flutter 中为标记图标设置动画?