Фон
Функция ниже вызывает две функции, которые обращаются к API, извлекают данные JSON, анализируют их и т. Д. c, а затем принимают эти данные и заполняет значения переменной объекта в моем классе View Controller.
func requestWordFromOxfordAPI(word: String, completion: (_ success: Bool) -> Void) {
oxfordAPIManager.fetchDictData(word: word)
oxfordAPIManager.fetchThesData(word: word)
completion(true)
}
Обычно, если была только одна функция, извлекающая данные, и я хотел вызвать новую функцию, которая принимает результаты данных и что-то с ними делает, я бы использовал метод делегата и вызывал его внутри закрытие функции извлечения данных.
Например:
Здесь я выбираю данные из базы данных Firebase и, если извлечение данных прошло успешно, я вызываю self.delegate?.populateWordDataFromFB(result: combinedModel)
. Поскольку замыкания происходят в отдельном потоке, это гарантирует, что функция populateWordDataFromFB выполняется только после завершения извлечения данных. Пожалуйста, поправьте меня, если я ошибаюсь. Я только недавно узнал об этом и все еще пытаюсь увидеть всю картину.
func readData(word: String) {
let docRef = db.collection(K.FBConstants.dictionaryCollectionName).document(word)
docRef.getDocument { (document, error) in
let result = Result {
try document.flatMap {
try $0.data(as: CombinedModel.self)
}
}
switch result {
case .success(let combinedModel):
if let combinedModel = combinedModel {
self.delegate?.populateWordDataFromFB(result: combinedModel)
} else {
self.delegate?.fbDidFailWithError(error: nil, summary: "\(word) not found, requesting from OxfordAPI")
self.delegate?.requestWordFromOxfordAPI(word: word, completion: { (success) in
if success {
self.delegate?.populateWordDataFromOX()
} else {print("error with completion handler")}
})
}
case .failure(let error):
self.delegate?.fbDidFailWithError(error: error, summary: "Error decoding CombinedModel")
}
}
}
Также обратите внимание на приведенный выше код, что, если данные не находятся в базе данных, я вызываю метод делегата, приведенный ниже, где я сталкиваюсь с моей проблемой.
self.delegate?.requestWordFromOxfordAPI(word: word, completion: { (success) in
if success {
self.delegate?.populateWordDataFromOX()
} else {print("error with completion handler")}
})
Моя проблема
С чем я борюсь, так это с тем, что обе функции oxfordAPIManager.fetchDictData(word: word)
и oxfordAPIManager.fetchThesData(word: word)
имеют замыкания.
Тело этих функций выглядит следующим образом:
if let url = URL(string: urlString) {
var request = URLRequest(url: url)
request.addValue(K.APISettings.acceptField, forHTTPHeaderField: "Accept")
request.addValue(K.APISettings.paidAppID , forHTTPHeaderField: "app_id")
request.addValue(K.APISettings.paidAppKey, forHTTPHeaderField: "app_key")
let session = URLSession.shared
_ = session.dataTask(with:request) { (data, response, error) in
if error != nil {
self.delegate?.apiDidFailWithError(error: error, summary: "Error performing task:")
return
}
if let safeData = data {
if let thesaurusModel = self.parseThesJSON(safeData) {
self.delegate?.populateThesData(thesModel: thesaurusModel, word: word)
}
}
}
.resume()
} else {print("Error creating thesaurus request")}
Я полагаю, что обе эти функции работают в отдельных потоках в фоновом режиме. Моя цель - вызвать другую функцию после запуска обеих функций oxfordAPIManager.fetchDictData(word: word)
и oxfordAPIManager.fetchThesData(word: word)
. Эти две функции будут заполнять значения объектной переменной в моем контроллере представления, которые я буду использовать в новой функции. Я не хочу, чтобы новая функция вызывалась до того, как переменная объекта в контроллере представления будет заполнена правильными данными, поэтому я попытался реализовать обработчик завершения. Функция обработчика завершения вызывается BEFORE , две функции завершаются, поэтому, когда новая функция пытается получить доступ к переменной объекта в View Controller, она пуста.
Это моя первая попытка реализовать обработчик завершения, и я попытался следовать некоторым другим сообщениям переполнения стека, но безуспешно. Также, если это неправильный подход, дайте мне знать, пожалуйста. Извините за длинное объяснение и спасибо за любой вклад.