iOS RxSwift-如何解开“ Optional <optional <t >>”或“ T ??”?

时间:2018-09-01 00:34:57

标签: swift unit-testing swift4 rx-swift rx-blocking

我正在使用以下逻辑通过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 :(得分:2)

是的,因此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

打个电话是否值得?

答案 1 :(得分:2)

这是一个答案,不需要您定义任何自己的函数:

return (try? subject.verifier.toBlocking().first()).flatMap { $0 } ?? 0

答案 2 :(得分:2)

还有其他两种选择,通过处理错误来避免使用double可选

第一个将错误移交给调用者

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 }
}

答案 3 :(得分:1)

我想出了另一个我认为您可能会喜欢的解决方案:

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

以上内容可让您简单地进行操作:

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

我试图为运算符赋予比try?更高的优先级,这样就不需要使用括号,但是我找不到解决方法。