RxSwiftでnilをフィルタリングする

September 20, 2016

自分で書いても良いんですが、一応RxSwift Communityが提供している RxOptionalというのがあるのでメモしておきます。

動機

nilをフィルタリングしたい。その際型もオプショナルじゃなくしたい。 たとえばObservable<String?> があったとして、nilをフィルタリングしつつObservable<String>にしたい。 要はObservable<E?>Observable<E> の変換を行いたい。

愚直にfilterでやると

let o = Observable<String?>.just(nil) 
o.filter { $0 != nil } // nilは弾けたけどこの型は `Observable<String?>のまま
o.filter { $0 != nil }.map { $0! } // うーん 

なのでやるなら

public protocol OptionalType {
    associatedtype Wrapped
    func map<U>(@noescape f: (Wrapped) throws -> U) rethrows -> U?
}

extension Optional: OptionalType { }

public extension ObservableType where E: OptionalType {
    public func filterNil() -> Observable<E.Wrapped> { ... }
}

みたいなのを自分で書く必要がある。

RxOptional

https://github.com/RxSwiftCommunity/RxOptional

やっていることは↑の実装と同じ。ただし便利なオペレータが他にも幾つか提供されている。

  • filterNil
  • replaceNilWith
  • errorOnNil
  • catchOnNil
  • distinctUntilChanged

また、以下のようなOccupiable というプロトコルを実装した型については他のオペレーターも使える。

public protocol Occupiable {
    var isEmpty: Bool { get }
    var isNotEmpty: Bool { get }
}
  • filterEmpty
  • errorOnEmpty
  • catchOnEmpty

RxOptionalがデフォルトで提供しているOccupiableの実装は以下。

extension String: Occupiable { }
extension Array: Occupiable { }
extension Dictionary: Occupiable { }
extension Set: Occupiable { }

使い方はREADMEに書いてある&コードも大した量じゃないので読んだほうが早いかも :innocent:

このエントリーをはてなブックマークに追加