Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RxSwift unwrap optional handy function?

Tags:

swift

rx-swift

Currently I have created a function unwrapOptional to safely unwrap the optional input in the stream.

    func unwrapOptional<T>(x: Optional<T>) -> Observable<T> {
       return x.map(Observable.just) ?? Observable.empty()
    }

    let aOpt: String? = "aOpt"
    _ = Observable.of(aOpt).flatMap(unwrapOptional).subscribeNext { x in print(x)}

    let aNil: String? = nil
    _ = Observable.of(aNil).flatMap(unwrapOptional).subscribeNext { x in print(x)}

    let a: String = "a"
    _ = Observable.of(a).flatMap(unwrapOptional).subscribeNext { x in print(x)}

   // output 
    aOpt
    a

What I want to archive is to create a handy function instead of using flatMap(unwrapOptional), for example

Observable.of(a).unwrapOptional()

Something I tried to do, but it never compiles...

extension ObservableType {
    func unwrapOptional<O : ObservableConvertibleType>() -> RxSwift.Observable<O.E> {
        return self.flatMap(unwrapOptional)
    }
}
like image 895
LoGary Avatar asked Apr 19 '16 05:04

LoGary


1 Answers

You want the unwrapOptional method to only work on observables that have optional type.

So you somehow have to constraint the Element of Observable to conform to the Optional protocol.

extension Observable where Element: OptionalType {
    /// Returns an Observable where the nil values from the original Observable are
    /// skipped
    func unwrappedOptional() -> Observable<Element.Wrapped> {
        return self.filter { $0.asOptional != nil }.map { $0.asOptional! }
    }
}

Unfortunately, Swift does not define such a protocol (OptionalType). So you also need to define it yourself

/// Represent an optional value
///
/// This is needed to restrict our Observable extension to Observable that generate
/// .Next events with Optional payload
protocol OptionalType {
    associatedtype Wrapped
    var asOptional:  Wrapped? { get }
}

/// Implementation of the OptionalType protocol by the Optional type
extension Optional: OptionalType {
    var asOptional: Wrapped? { return self }
}
like image 189
tomahh Avatar answered Sep 19 '22 17:09

tomahh