首页 > 解决方案 > 如何使方法同步执行方法

问题描述

我尝试使用 DispatchQueue 和 DispatchGroup 但它仍然是异步的,我也尝试了 dispatchQueue.Async 和 dispathQueue.sync 都没有工作。

myFunc 是在 init() 中调用的函数,它本身调用 2 个函数,getArrOneData() 和 getArrTwoData([ArrOneType])。

第一个函数从 firestore 下载 ArrOneType 数据并返回一个初始化为字段的数组。

第二个函数使用从第一个函数下载的数据/字段来初始化 ArrTwoType 中的字段,同时从 firestore 下载其他相关的 ArrTwoType 数据以作为数组返回。

所以问题是它仍然是异步的。在这种情况下如何正确使用 DispatchQueue 和 DispatchGroup?

谢谢

注意:获取 arrTwoData 主要是伪代码

func myFunc(){
        let group = DispatchGroup()
        let dispatchQueue = DispatchQueue.global(qos: .default)
        group.enter()
        dispatchQueue.sync {
            self.arrOne = self.getArrOneData()//getArrOneData gets data from firestore
            group.leave()
        }

dispatchQueue.sync {
        group.enter()
    self.arrTwo = self.getArrTwoData(inputArr: self.arrOne)//getArrTwoData gets data from firestore 

    group.leave()
         }
    }

//ArrOneType is an array field in ArrTwoType
func getArrTwoData(inputArr: [ArrOneType]) -> [ArrTwoType]{

var result = [ArrTwoType]()

//retrieving data from firestore, code excluded...
    for document in querySnapshot!.documents {
   let data = document.data()

name = data["Name"] as? String ?? "Name Unknown"

//returns an array which is a subset of inputArr filtered by name, however
//I dont think the inputArr is populated at this point when I run the program
var field2:[ArrOneType] = someFunc(name, inputArr)

var x = ArrTwoType(name: name, field2: field2)

result.append(x)
    }
  }
}
return result
}

标签: swiftasynchronoussynchronization

解决方案


如果您有两个请求,一个使用来自一个的响应来准备下一个请求,则想法是@escaping对所有异步方法使用完成处理程序闭包,例如

func getArrayOneData(completion: @escaping (Result<[ArrayOneType], Error>) -> Void) {
    someAsynchronousMethod {
        let values: [ArrayOneType] = ...
        completion(.success(values))
    }
}

func getArrayTwoData(for typeOneValues: [ArrayOneType], completion: @escaping (Result<[ArrayTwoType], Error>) -> Void) {
    someAsynchronousMethod(for: typeOneValues) {
        let values: [ArrayTwoType] = ...
        completion(.success(values))
    }
}

然后您可以执行以下操作:

func getEverything(completion: @escaping (Result<[ArrayTwoType], Error>) -> Void) {
    getArrayOneData { result in
        switch result {
        case .failure(let error):
            print(error)

        case .success(let typeOneValues):
            getArrayTwoData(for: typeOneValues) { result in
                switch result {
                case .failure(let error):
                    print(error)

                case .success(let typeTwoValues):
                    completion(.success(typeTwoValues))
                }
            }
        }
    }
}

请注意,不需要调度组。将完成处理程序添加到异步方法后,我们可以从第一个完成处理程序中调用第二个方法。


推荐阅读