带有投射的{RxSwift Observable过滤器

时间:2017-04-25 13:33:57

标签: swift3 rx-swift

免责声明:我是一个半Rx的新手,所以很有可能这个想法完全疯了:)

我尝试编写ObservableType过滤器,它只会传递某种类型,但会传递该类型,而不是原始序列类型。这就是我到目前为止所提出的:

extension ObservableType where Self.E: RxFilterableType {
  func filterByCast<T: RxFilterableType>(class: T.Type) -> Observable<T> {
    let retval = PublishSubject<T>()
    self.subscribe { event in
      switch event {
      case .next(let element):
        if let passed = element as? T {
          retval.onNext(passed)
        }
      case .error(let error):
        retval.onError(error)
      case .completed:
        retval.onCompleted()
      }
    }
    return retval
  }
}

func test() {
  class A: RxFilterableType {}
  class B: RxFilterableType {}

  let array: [RxFilterableType] = [A(), B()]
  let observable: Observable<RxFilterableType> = Observable.from(array)
  let observableCasted: Observable<A> = observable.filterByCast(class: A.self)
}

这有两个问题:较小的问题是内部subscribe一次性不被处理。理想情况下,我希望将处置责任转移到返回值上,但我可以将处理器作为参数。我不在乎。

更大的问题是最后一个测试线上的编译器异议:

  

使用&#39; RxFilterableType&#39;作为符合协议的具体类型&#39; RxFilterableType&#39;不支持

令人害怕的是,我担心,编译器没有足够的信息来推断我想要做什么,尽管我已经在绝望的帮助中添加了超过必要的提示可怜的家伙。

1 个答案:

答案 0 :(得分:8)

如果你将它放在配置为使用RxSwift的游乐场中,它将起作用:

import RxSwift

extension ObservableType {
    func filterByCast<T>() -> Observable<T> {
        return self.filter { $0 is T }.map { $0 as! T }
    }
}

protocol Foo { }
struct A: Foo { }
struct B: Foo { }

let array: [Foo] = [A(), B()]
let observable = Observable.from(array)
let casted: Observable<A> = observable.filterByCast()
_ = casted.subscribe(onNext: { print($0) })

或者,如果您不喜欢指定casted的类型:

extension ObservableType {
    func filterByCast<T>(_ class: T.Type) -> Observable<T> {
        return self.filter { $0 is T }.map { $0 as! T }
    }
}

protocol Foo { }
struct A: Foo { }
struct B: Foo { }

let array: [Foo] = [A(), B()]
let observable = Observable.from(array)
let casted = observable.filterByCast(A.self)
_ = casted.subscribe(onNext: { print($0) })

要求将类类型作为参数,这是你的一个很好的接触。我没有想过这样做。