Функция возвращает результат до отработки completionHandler`а другой функции, как исправить?
столкнулся с такой проблемой, и не могу понять, какие есть пути решения данной проблемы.
Для начала предположим, что у меня есть следующая функция
func summ(x: Int, y: Int, completionHandler: @escaping (Int) -> ()) {
let result: Int = x + y
completionHandler(result)
}
Далее мы хотим в другой функции как то обработать результат функции, указанной выше, и вернуть обработанное значение.
func summ(x: Int, y: Int, completionHandler: @escaping (Int) -> ()) {
let result: Int = x + y
completionHandler(result)
}
func getResult(x: Int, y: Int) -> (String) {
let resultString: String = ""
summ(x, y) { result in
resultString = "Результат: \(String(result))"
}
return resultString
}
Но при вызове let resultString = getResult(x = 15, y = 10) я получаю просто пустую строку.
При попытках найти ошибку, понял, что в данный метод создает let resultString: String = "" а после чего сразу возвращает эту переменную return resultString, и только После этого начинает работу completionHandler
Я бы хотел, чтобы мой return возвращал значение ПОСЛЕ того, как полностью отработает completionHandler, а не до этого.
Замечание: Я предположу, что скорее всего будет предложено прям в комплишн хэндлере и обновить значение, присвоив ему правильное, но данное решение мне не подходит. В данном случае функции были взяты из головы, для упрощения понимания, в реальности, я с помощью CoreLocation получаю координаты по названию города, а после чего, в другой функции, мне нужно вернуть значение погоды по координатам, которые я получаю, как назло, в комплишн хэндлере...
Т.к. я только начал учить язык, возможно, я как то не так объяснил свою проблему, но надеюсь на понимание.
Про возможное решение, которое мне не совсем подходит:
let resultString: String = ""
func summ(x: Int, y: Int, completionHandler: @escaping (Int) -> ()) {
let result: Int = x + y
completionHandler(result)
}
func getResult(x: Int, y: Int) {
summ(x, y) { result in
resultString = "Результат: \(String(result))"
self.resultString = resultString
}
}
Ответы (1 шт):
Если отбросить новые фичи языка, то наверное это может выглядеть так:
func getResult(x: Int, y: Int) -> (String) {
var resultString: String = ""
let dispatchGroup = DispatchGroup()
dispatchGroup.enter()
summ(x: x, y: y) { result in
resultString = "Результат: \(String(result))"
dispatchGroup.leave()
}
dispatchGroup.wait()
return resultString
}
Получается блокирующая функция, которую нельзя вызывать из .main
UPD: Все-таки для начинающего DispatchGroup слишком сложно, можно обойтись классическим решением попроще (никаких глобальных переменных и ожиданий значений из асинхронных функций):
func summ(x: Int, y: Int, completionHandler: @escaping (Int) -> ()) {
let result: Int = x + y
completionHandler(result)
}
func getResult(x: Int, y: Int) {
summ(x, y) { result in
updateResult("Результат: \(String(result))")
}
}
func updateResult(strResult: String) {
// здесь делайте все что вам нужно с новым значением
}