Операция ветвления Combine, flatMap и нечетная странность - PullRequest
0 голосов
/ 09 марта 2020

Контекст

Я следую примеру WWD C 2019 722 https://developer.apple.com/videos/play/wwdc2019/722/ и WWD C 2019 721 https://developer.apple.com/videos/play/wwdc2019/721/ и делаю поле с проверкой запускает асинхронную проверку сети на поле.

Что должно произойти, как упоминалось в докладе, это то, что поле имени пользователя должно:

  1. Debounce
  2. Показать индикатор загрузки
  3. Выполнить сетевой запрос
  4. Завершить сетевой результат
  5. Скрыть индикатор загрузки
  6. И показать или скрыть сообщение проверки в результате ответа сети

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

let a = $firstName
    .debounce(for: .seconds(0.5), scheduler: DispatchQueue.main)
    .flatMap { name -> AnyPublisher<String, Never> in
        if name == "" {
            return Just(name)
                .eraseToAnyPublisher()
        } else {
            return Just(name)
                .handleEvents(receiveOutput: { _ in self.isFirstNameLoading = true})
                .delay(for: .seconds(2), scheduler: DispatchQueue.main)
                .handleEvents(receiveOutput: { _ in self.isFirstNameLoading = false})
                .eraseToAnyPublisher()
        }
    }
    .map { name -> Bool in name != "Q" }
    .assign(to: \.isFirstNameValid, on: self)

Отладка ждет, пока ввод не приостановится. flatMap действует как условное ветвление в потоке операторов Combine: если значение пусто, не беспокойтесь о сетевом запросе; иначе, если значение имеет значение после отката, выполните сетевой запрос. И, наконец, мой пример, что «Q» всегда является ошибкой в ​​фиктивных целях.

Однако небольшая проблема заключается в том, что отладка происходит до ветвления. Я хотел бы переместить debounce в ветвь else условного выражения, например, так.

let a = $firstName
    .flatMap { name -> AnyPublisher<String, Never> in
        if name == "" {
            return Just(name)
                .eraseToAnyPublisher()
        } else {
            return Just(name)
                .debounce(for: .seconds(0.5), scheduler: DispatchQueue.main)
                .handleEvents(receiveOutput: { _ in self.isFirstNameLoading = true})
                .delay(for: .seconds(2), scheduler: DispatchQueue.main)
                .handleEvents(receiveOutput: { _ in self.isFirstNameLoading = false})
                .eraseToAnyPublisher()
        }
    }
    .map { name -> Bool in name != "Q" }
    .assign(to: \.isFirstNameValid, on: self)

Когда это происходит, истинная ветвь условного выражения (пустой ввод) выполняется правильно, и map + assign после того, как flatMap работает правильно. Однако, когда вход имеет значение, и ветвь else условного запуска выполняется, ничего после отката не запускается вообще.

Я попытался переключить DispatchQueue на OperationQueue.main и RunLoop.main, но безрезультатно.

Сохранение отката до условной работы пока нормально, но мне интересно, Я делаю что-то не так с моей попыткой поместить это в ветку. Мне также интересно, если бы это был правильный способ сделать "ветвление" в операторах с Combine, особенно с моим использованием flatMap и Just().

Любая помощь будет оценена!

1 Ответ

2 голосов
/ 09 марта 2020

A Just только когда-либо производит один выход. Присоединение debounce к нему ничего не изменит. В лучшем случае это просто задержит вывод Just на интервал отката. В худшем случае, есть ошибка, которая вообще не работает, как это звучит, исходя из вашего описания.

...