iOS RxSwift - Как развернуть `Optional <Optional <T>>` или `T ??`? - PullRequest
0 голосов
/ 01 сентября 2018

Я использую приведенную ниже логику для проверки состояния моего предмета с помощью RxBlocking. Я получаю странное значение Int?? из try? subject.verifier.toBlocking().first().

Синтаксис ниже радует компилятор, но у меня кровоточат глаза.

Как получить развернутое значение из ожидания RXBlocking?

func checkSubjectState() -> Int
    {
      let updatedChecksum = try? subject.verifier.toBlocking().first() ?? 0
      return updatedChecksum ?? 0
    }

let expectedCheckSum = checkSubjectState()
expect(expectedCheckSum).to(equal(knownValue))

Ответы [ 4 ]

0 голосов
/ 01 сентября 2018

Есть две другие альтернативы, позволяющие избежать двойного необязательного обращения с ошибкой

Первым передает ошибку вызывающему абоненту

func checkSubjectState() throws -> Int
{
  return try subject.verifier.toBlocking().first() ?? 0
}

Второй добавляет do - catch блок

func checkSubjectState() -> Int
{
    do { return try subject.verifier.toBlocking().first() ?? 0 } 
    catch { return 0 }
}
0 голосов
/ 01 сентября 2018

Я придумала другое решение, которое, я думаю, вам может понравиться больше:

infix operator ???: NilCoalescingPrecedence
func ???<T>(opt: T??, val: @autoclosure () -> T) -> T {
    return ((opt ?? val()) ?? val())
}

Вышесказанное позволит вам просто:

return (try? subject.verifier.toBlocking().first()) ??? 0

Я пытался дать оператору более высокий приоритет, чем try?, чтобы паренсы не были нужны, но я не мог найти способ сделать это.

0 голосов
/ 01 сентября 2018

Вот ответ, который не требует от вас определения какой-либо из ваших собственных функций:

return (try? subject.verifier.toBlocking().first()).flatMap { $0 } ?? 0
0 голосов
/ 01 сентября 2018

Да, поэтому first() может выдать , а возвращает тип Optional, поэтому try? first() возвращает Optional<Optional<Int>> или Int??. Честно говоря, я думаю, что функция first() написана плохо. Он должен либо выбросить , либо вернуть необязательно, но не оба.

Вы можете написать оператор flattened:

public protocol OptionalType {
    associatedtype Wrapped
    var value: Wrapped? { get }
}

extension Optional: OptionalType {
    public var value: Wrapped? {
        return self
    }
}

extension Optional where Wrapped: OptionalType {
    var flattened: Wrapped.Wrapped? {
        switch self {
        case let .some(opt):
            return opt.value
        case .none:
            return nil
        }
    }
}

Что позволит вам сделать:

let expectedCheckSum = (try? subject.verifier.toBlocking().first()).flattened ?? 0

Считаете ли вы, что оно того стоит или нет, это ваш звонок.

...