RxSwift의 새로운 Single, Maybe, Completable 소스를 읽어 보았습니다.

13438 단어 SwiftRxSwift
RxSwift에 새로 추가된 Single, Maybe, Completable 에서 새로운 Units들을 조사하는데 RxSwift는 문서가 없었기 때문에, 소스를 읽어 본 메모.

구현 파일



구현은 여기 RxSwift/PrimitiveSequence.swift

새로운 Units는 Traits 라는 Group으로 분류되고 있다.
Traits = 성질이라는 의미. 과연.



기본 구조체 정의



우선, PrimitiveSequence 라는 struct가 정의되고 있다
이 struct에는 Generics에서 Trait(性質)Element(要素)를 지정할 수 있다.ElementsObservable 의 응답의 형태가 된다.

PrimitiveSequence
/// Observable sequences containing 0 or 1 element.
public struct PrimitiveSequence<Trait, Element> {
    fileprivate let source: Observable<Element>

    init(raw: Observable<Element>) {
        self.source = raw
    }
}

새로운 유닛 정의



Units
/// Sequence containing exactly 1 element
public enum SingleTrait { }
/// Represents a push style sequence containing 1 element.
public typealias Single<Element> = PrimitiveSequence<SingleTrait, Element>

/// Sequence containing 0 or 1 elements
public enum MaybeTrait { }
/// Represents a push style sequence containing 0 or 1 element.
public typealias Maybe<Element> = PrimitiveSequence<MaybeTrait, Element>

/// Sequence containing 0 elements
public enum CompletableTrait { }
/// Represents a push style sequence containing 0 elements.
public typealias Completable = PrimitiveSequence<CompletableTrait, Swift.Never>
SingleTrait, MaybeTraitCompletableTraitSingle는 처음으로 알았다. 아무것도 돌려주지 않는 것은 Void가 아니고 Maybe 로 나타내는 것 같다.
( Never - Swift Standard Library | Apple Developer Documentation )

PrimitiveSequenceType의 프로토콜 정의



PrimitiveSequenceType
/// Observable sequences containing 0 or 1 element
public protocol PrimitiveSequenceType {
    /// Additional constraints
    associatedtype TraitType
    /// Sequence element type
    associatedtype ElementType

    // Converts `self` to primitive sequence.
    ///
    /// - returns: Observable sequence that represents `self`.
    var primitiveSequence: PrimitiveSequence<TraitType, ElementType> { get }
}

extension PrimitiveSequence: PrimitiveSequenceType {
    /// Additional constraints
    public typealias TraitType = Trait
    /// Sequence element type
    public typealias ElementType = Element

    // Converts `self` to primitive sequence.
    ///
    /// - returns: Observable sequence that represents `self`.
    public var primitiveSequence: PrimitiveSequence<TraitType, ElementType> {
        return self
    }
}

여기서 Completable의 프로토콜이 정의됩니다.
솔직히 여기에 Protocol을 정의하지만 잘 모르겠습니다. . . 어때?
앞으로 비슷한 Unit이 나왔음에도 대응할 수 있도록?
제네릭스를 typealias로 두는 것이, 후술의 protocol extension은 쓰기 쉬워질 것 같다.

PrimitiveSeaquence를 ObservableConvertibleType에 적합



PrimitiveSequence
extension PrimitiveSequence: ObservableConvertibleType {
    /// Type of elements in sequence.
    public typealias E = Element

    /// Converts `self` to `Observable` sequence.
    ///
    /// - returns: Observable sequence that represents `self`.
    public func asObservable() -> Observable<E> {
        return source
    }
}
PrimitiveSequence 에 적합합니다.
하면 Swift.Never 는 Observable도 될 수 있습니다.
좁은 강은 넓게 할 수 있다. 반대는 불가.

각 유닛마다 구현



그 후는 각 성질마다 Event나, Never , PrimitiveSequenceType 등의 실장이 된다.

SingleEvent
public enum SingleEvent<Element> {
    /// One and only sequence element is produced. (underlying observable sequence emits: `.next(Element)`, `.completed`)
    case success(Element)

    /// Sequence terminated with an error. (underlying observable sequence emits: `.error(Error)`)
    case error(Swift.Error)
}


각 성질에 대한 function 구현은 ObservableConvertibleType의 Extension으로 구현된다.
where 로 제네릭스의 형태를 지정하는 것으로, 적합하는 경우만 이 extension를 사용할 수 있게 된다.

PrimitiveSequenceType (SingleTrait)
extension PrimitiveSequenceType where TraitType == SingleTrait {
    public typealias SingleObserver = (SingleEvent<ElementType>) -> ()

    public func subscribe(_ observer: @escaping (SingleEvent<ElementType>) -> ()) -> Disposable {
        var stopped = false
        return self.primitiveSequence.asObservable().subscribe { event in
            if stopped { return }
            stopped = true

            switch event {
            case .next(let element):
                observer(.success(element))
            case .error(let error):
                observer(.error(error))
            case .completed:
                rxFatalError("Singles can't emit a completion event")
            }
        }
    } 

   // その他の実装は省略
}
PrimitiveSequencecreate 를 봐도 알 수 있듯이, subscribe 또는 PrimitiveSequenceType 밖에 흐르지 않는다.Single 가 흐르는 것은 subscribe 의 사양적으로 있을 수 없기 때문에 fatalError로 앱이 떨어진다.

그 외



그 외의 일반적인 success

좋은 웹페이지 즐겨찾기