Возврат значения из блока завершения / закрытия, используемого в методе источника данных

У меня есть пользовательское представление, которое будет отображаться в представлении коллекции. Представление будет добавлено в виде стека, встроенного в контроллер представления. Метод источника данных предоставляется для предоставления объекта представления.

Теперь вот проблема, прежде чем добавить свой пользовательский вид в стек, мне нужно сначала сделать вызов шлюза, чтобы проверить, разрешено ли отображение вида или нет. Поскольку шлюз вызова является асинхронным и возвращает мне ответ в обратном вызове. Основываясь на обратном вызове, мне нужно создать экземпляр представления и вернуться в предоставляемый обратный вызов источника данных.

Вот демонстрационный код только для лучшего понимания. Прости меня за мои ужасные соглашения об именах.

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
})
Другие вопросы по тегам