Возврат значения из блока завершения / закрытия, используемого в методе источника данных
У меня есть пользовательское представление, которое будет отображаться в представлении коллекции. Представление будет добавлено в виде стека, встроенного в контроллер представления. Метод источника данных предоставляется для предоставления объекта представления.
Теперь вот проблема, прежде чем добавить свой пользовательский вид в стек, мне нужно сначала сделать вызов шлюза, чтобы проверить, разрешено ли отображение вида или нет. Поскольку шлюз вызова является асинхронным и возвращает мне ответ в обратном вызове. Основываясь на обратном вызове, мне нужно создать экземпляр представления и вернуться в предоставляемый обратный вызов источника данных.
Вот демонстрационный код только для лучшего понимания. Прости меня за мои ужасные соглашения об именах.
func customeViewInStack(customView: UIView) -> [UIView]? {
if viewIsAllowedToBeDisplayed {
self.downloadViewContent(onCompletionHandler: { contentDownloadSuccessfull in
if contentDownloadSuccessfull
// Return new instance of my custom view
else
// return nil
})
}
return nil
}
Все предложения, которые я прочитал, касались использования замыкания для передачи значения, но из-за метода источника данных и обратного вызова в вызове шлюза мне нужно использовать устаревшую инструкцию возврата.
Редактировать 1
Я обновил фрагмент кода для лучшего понимания.Я не могу изменить сигнатуру функции, так как она является частью фреймворка и метода источника данных.
Также этот метод разделяется между различными функциями. Под этим я подразумеваю, что различные представления будут добавляться в виде стека, и у них есть свои собственные условные проверки, добавлять их или нет. Поэтому в основном я пытаюсь достичь того, пока я не получу ответ от операции шлюза, выполнение программы не должно продолжаться. Я пытался использовать класс DispatchGroup, но не смог достичь своей цели.
Может ли кто-нибудь подсказать мне, как мне решить эту проблему?
Спасибо
2 ответа
Что касается этого, правильное решение состоит в том, чтобы не возвращать что-то из функции, а вместо этого дать завершение этой функции.
func customeViewInStack(customView: UIView, completion: @escaping ([UIView]?) -> Void) {
self.checkIfViewShouldBeShown(onCompletionHandler: { shouldDisplayView in
completion(shouldDisplayView ? [...(put the stack of views to return here))] : nil)
})
}
РЕДАКТИРОВАТЬ: я плохо читал в первый раз, поэтому я улучшил свой ответ.
Поскольку вам нужно передать его в представление коллекции, я предлагаю вам сохранить его и перезагрузить коллекцию:
private var viewsForCollection: [UIView] = []
customeViewInStack(customView: UIView(), completion: { [weak self] views in
self?.viewsForCollection = views ?? [] // I guess optionality for array is unnecessary
self?.collectionView.reloadData()
})
Сначала у вас будет пустая коллекция, но как только ваши представления будут готовы, вы можете перезагрузить ее.
Вам нужно будет объявить свой собственный блок завершения и использовать его, чтобы получить новый вид:
Вот как выглядит это объявление:
// Declaration
func customeViewInStack(customView: UIView, completion: @escaping ([UIView]? -> ()) {
self.checkIfViewShouldBeShown(onCompletionHandler: { shouldDisplayView in
if shouldDisplayView
// Call the completion block with the views
completion(views)
else
// Call the completion block with nil
completion(nil)
})
}
И затем при использовании этого, вы будете использовать его так же, как вы использовали checkIfViewShouldBeShown
метод:
customViewInStack(customView: customView, completion: { views in
guard let views = views else {
// Views are nil
}
// Do what you need to do with views
})