Объединить: как заменить / отловить ошибку, не заполнив оригинального издателя? - PullRequest
0 голосов
/ 02 ноября 2019

Учитывая следующий код:

    enum MyError: Error {
        case someError
    }

    myButton.publisher(for: .touchUpInside).tryMap({ _ in
        if Bool.random() {
            throw MyError.someError
        } else {
            return "we're in the else case"
        }
    })
        .replaceError(with: "replaced Error")
        .sink(receiveCompletion: { (completed) in
            print(completed)
        }, receiveValue: { (sadf) in
            print(sadf)
        }).store(in: &cancellables)

Всякий раз, когда я нажимаю кнопку, я получаю we're in the else case, пока Bool.random() не станет истиной - теперь выдается ошибка. Я пробовал разные вещи, но у меня не получилось поймать / заменить / проигнорировать ошибку и просто продолжить после нажатия кнопки.

В примере кода мне бы хотелось иметь, например, следующий вывод

we're in the else case
we're in the else case
replaced Error
we're in the else case
...

вместо этого я получаю finished после replaced error, и никакие события не отправляются.

Редактировать Если издатель имеет AnyPublisher<String, Error>, как я могу преобразовать его вAnyPublisher<String, Never> без завершения при возникновении ошибки, т. Е. Игнорировать ошибки, выданные первоначальным издателем?

Ответы [ 3 ]

0 голосов
/ 13 ноября 2019

Я предлагаю использовать Publisher с typealias Failure = Never и выводить как опциональный результат: typealias Output = Result<YourSuccessType, YourFailtureType>

0 голосов
/ 13 ноября 2019

Для этого вы можете использовать оператор catch и Empty издатель:

let stringErrorPublisher = Just("Hello")
    .setFailureType(to: Error.self)
    .eraseToAnyPublisher() // AnyPublisher<String, Error>

let stringPublisher = stringErrorPublisher
    .catch { _ in Empty<String, Never>() }
    .eraseToAnyPublisher() // AnyPublisher<String, Never>
0 голосов
/ 12 ноября 2019

Просто вставьте flatMap, как показано ниже, и вы сможете добиться желаемого.

   self.myButton.publisher(for: \.touchUpInside).flatMap{
            (data: Bool) in
        return Just(data).tryMap({ _ -> String in
        if Bool.random() {
            throw MyError.someError
        } else {
            return "we're in the else case"
        }}).replaceError(with: "replaced Error")
    }.sink(receiveCompletion: { (completed) in
            print(completed)
        }, receiveValue: { (sadf) in
            print(sadf)
       }).store(in: &cancellables)

Рабочая модель выглядит следующим образом:

 Just(parameter).
 flatMap{ (value)->AnyPublisher<String, Never> in 
 return MyPublisher(value).catch { <String, Never>() } 
 }.sink(....)

Если мы используем приведенный выше пример, это может бытьнапример:

let firstPublisher    = {(value: Int) -> AnyPublisher<String, Error> in
           Just(value).tryMap({ _ -> String in
           if Bool.random() {
               throw MyError.someError
           } else {
               return "we're in the else case"
            }}).eraseToAnyPublisher()
    }

    Just(1).flatMap{ (value: Int) in
        return  firstPublisher(value).replaceError(with: "replaced Error")
   }.sink(receiveCompletion: { (completed) in
            print(completed)
        }, receiveValue: { (sadf) in
            print(sadf)
       }).store(in: &cancellables)

Здесь вы можете заменить firstPublisher на AnyPublisher, который принимает один параметр.

Также здесь, firstPublisher имеет только одно значение, он может выдавать только одно значение. Но если ваш издатель может выдать несколько значений, он не завершится до того, как будут выпущены все значения.

...