Это потому, что valueOutOfFunction
происходит внутри того замыкания, которое вызывается асинхронно с оператором print. Кроме того, вы выполняете завершение вне оператора else , который может запускаться до того, как завершится ваш запрос l oop. То, что вы хотите сделать, это контролировать поток изнутри самого затвора следующим образом:
// move com(arrayOfTuples) up into the else block but outside of the for loop
func handleQuery() {
loadQuery { doStuffWithResult($0) }
// This line will run before the first line of doStuffWithResult
// It would be best to end the function logic at loadQuery
}
func doStuffWithResult(_ arrayOfTuples: [(Int, String)]) {
print(arrayOfTuples)
// Do other work here
}
То, на что вы смотрите, это поток управления. Вы хотите выполнить X if Y
произошло и Z if !Y
верно?
Я бы рекомендовал просмотреть тип результата swift . Это поможет вам управлять потоком управления с помощью замыканий.
Пример:
typealias QueryResult = [(Int, String)]
enum QueryErrors: Error {
case couldNotFind
}
func loadQuery(_ result: @escaping (Result<QueryResult, Error>) -> Void) {
db.collection("Data").whereField("age", isGreaterThanOrEqualTo: 1).whereField("age", isLessThanOrEqualTo: 50).whereField("gender", isEqualTo: "F").getDocuments() { (querySnapshot, err) in
guard let documents = querySnapshot?.documents.enumerated() else {
// I think enumerated will give you an array of tuples... if not add this to the end of that line. After enumerated but before else
// enumerated().compactMap { ($0, $1) }
result(.failure(err ?? QueryErrors.couldNotFind))// passes back Firebase error if it exists or default error if it doesn't
return
}
result(.success(documents))
}
}
// how it works
loadQuery() { result in
switch(result) {
case .success(let arr): print(arr)
case .failure(let error): print(error)
}
}