返回

RXSwift源码解析3(操作符 map)

IOS

引子

在RxSwift中,map操作符是一个强大的工具,它允许我们变换序列中的每个元素,产生一个新的序列。本文将深入探究map操作符的源码,揭示其内部工作原理。

map操作符的实现

map操作符的实现位于ObservableType扩展中。其签名如下:

public func map<ResultType>(_ transform: @escaping (Element) throws -> ResultType) -> Observable<ResultType>

该方法接受一个闭包transform作为参数,该闭包将源序列中的每个元素变换为一个新值。

内部,map方法构造一个Map对象,该对象继承自ProducerMap对象的run方法被重写为MapSink,它作为map转换前的源序列。

MapSink

MapSink是一个订阅者,负责变换源序列中的每个元素。它实现如下:

final class MapSink<SourceType, ResultType>: Sink<ResultType> {
    typealias Parent = Map<SourceType, ResultType>
    
    override func run(_ parent: Parent, subscriber: SubscriberBase<ResultType>) {
        parent.source.subscribe(AnyObserver { event in
            switch event {
            case .next(let value):
                do {
                    let transformedValue = try parent.transform(value)
                    subscriber.on(.next(transformedValue))
                } catch let error {
                    subscriber.on(.error(error))
                }
            case .error(let error):
                subscriber.on(.error(error))
            case .completed:
                subscriber.on(.completed)
            }
        })
    }
}

run方法中,MapSink订阅源序列,并为每个元素调用闭包transform进行变换。如果变换成功,则发射变换后的值。如果变换失败,则发射错误。

使用示例

让我们通过一个示例来说明map操作符的用法:

let numbers = Observable.of(1, 2, 3, 4, 5)

// 将每个数字映射为其平方
let squaredNumbers = numbers.map { $0 * $0 }

// 订阅并打印平方数
squaredNumbers.subscribe(onNext: { print($0) })

输出:

1
4
9
16
25

结论

通过深入剖析map操作符的源码,我们了解了其内部工作原理。map操作符通过Map对象和MapSink订阅者协同工作,高效地变换源序列中的每个元素,产生一个新的序列。理解这些内部细节对于充分利用RxSwift的强大功能至关重要。