Combine核心概念
Combine主要有3大核心概念:Publisher,Operator和Subscriber:
Publisher
是数据的提供者,它提供了最原始的数据,不管这个数据是从什么地方获取的。如果把pipline想象成一条包子生产线,那么Publisher就表示食材Subscriber
是数据的接收者,它要求接收的数据必须是处理好的,同样把pipline想象成一条包子生产线,则Subscriber就是成品包子,而不是中间产物(菜馅等)Operator
是中间处理过程,它上下联通Publisher和Subscriber,对Publisher输出地数据进行处理,然后返回成品数据给Subscriber
Publisher
public protocol Publisher {
/// The kind of values published by this publisher.
associatedtype Output
/// The kind of errors this publisher might publish.
///
/// Use `Never` if this `Publisher` does not publish errors.
associatedtype Failure : Error
/// Attaches the specified subscriber to this publisher.
///
/// Implementations of ``Publisher`` must implement this method.
///
/// The provided implementation of ``Publisher/subscribe(_:)-4u8kn``calls this method.
///
/// - Parameter subscriber: The subscriber to attach to this ``Publisher``, after which it can receive values.
func receive<S>(subscriber: S) where S : Subscriber, Self.Failure == S.Failure, Self.Output == S.Input
}
从上边的代码,我们可以分析出3点重要信息:
Publisher
是一个协议,我们后续用到的所有publishers都实现了这个协议Publisher/receive(subscriber:)
是该协议的核心方法,它接受的参数subscriber
需要实现Subscriber
协议,这就是Operator
和Subscriber
能够连接Publisher
原因Self.Failure == S.Failure, Self.Output == S.Input
这个条件限制了Publisher
输出的数据类型必须跟Subscriber
输入的数据类型保持一致
Publisher/receive(subscriber:)
并没有限制Subscriber的数量,因此 Publisher
可以接受多个订阅。
Subscriber
public protocol Subscriber : CustomCombineIdentifierConvertible {
/// The kind of values this subscriber receives.
associatedtype Input
/// The kind of errors this subscriber might receive.
///
/// Use `Never` if this `Subscriber` cannot receive errors.
associatedtype Failure : Error
/// Tells the subscriber that it has successfully subscribed to the publisher and may request items.
///
/// Use the received ``Subscription`` to request items from the publisher.
/// - Parameter subscription: A subscription that represents the connection between publisher and subscriber.
func receive(subscription: Subscription)
/// Tells the subscriber that the publisher has produced an element.
///
/// - Parameter input: The published element.
/// - Returns: A `Subscribers.Demand` instance indicating how many more elements the subscriber expects to receive.
func receive(_ input: Self.Input) -> Subscribers.Demand
/// Tells the subscriber that the publisher has completed publishing, either normally or with an error.
///
/// - Parameter completion: A ``Subscribers/Completion`` case indicating whether publishing completed normally or with an error.
func receive(completion: Subscribers.Completion<Self.Failure>)
}
我们仔细分析上边的代码,同样会得到以下几个重要信息:
Subscriber
实现了CustomCombineIdentifierConvertible
协议,用于标记唯一身份Subscriber
同样是一个协议Subscriber/receive(subscription:)
该方法由Subscriber
实现,但是由Publisher
来调用,Publisher
调用了该方法后会传递一个实现了Subscription
协议的实例,Subscriber
使用该实例发送request
请求数据Subscriber
实现了Subscriber/receive(_:)
协议,Publisher
调用该方法发送数据Subscriber
实现了Subscriber/receive(completion:)
协议,Publisher
调用该方法发送结束事件(.finished
或.failure
)Subscriber
只接收输入数据
****在真实的开发中,我们用到最多的Subscriber
是assign
和sink
。
Operator
常用的Operator
:
["scan", "tryScan", "map/tryMap", "flatMap","setFailureType",
"compactMap/tryCompactMap", "filter/tryFilter", "removeDuplicates",
"replace", "collect", "ignoreOutput", "reduce","max", "min", "count",
"first", "last", "drop", "prepend", "dropFirst", "prefix", "output",
"combineLatest","merge", "zip", "allSatisfy", "contains", "catch",
"assertNoFailure", "retry", "mapError", "switchToLatest", "debounce",
"delay", "measureInterval", "throttle", "timeout", "encode", "decode",
"share", "multicast","breakpoint", "breakpointOnError", "handleEvents",
"print", "receive", "subscribe"]
在Combine中,Operator
是函数:
extension Publishers {
/// A publisher that transforms all elements from the upstream publisher with a provided closure.
public struct Map<Upstream, Output> : Publisher where Upstream : Publisher {
/// The kind of errors this publisher might publish.
///
/// Use `Never` if this `Publisher` does not publish errors.
public typealias Failure = Upstream.Failure
/// The publisher from which this publisher receives elements.
public let upstream: Upstream
/// The closure that transforms elements from the upstream publisher.
public let transform: (Upstream.Output) -> Output
public init(upstream: Upstream, transform: @escaping (Upstream.Output) -> Output)
/// Attaches the specified subscriber to this publisher.
///
/// Implementations of ``Publisher`` must implement this method.
///
/// The provided implementation of ``Publisher/subscribe(_:)-4u8kn``calls this method.
///
/// - Parameter subscriber: The subscriber to attach to this ``Publisher``, after which it can receive values.
public func receive<S>(subscriber: S) where Output == S.Input, S : Subscriber, Upstream.Failure == S.Failure
}
}
从上边的代码中,我们分析出以下几个重要信息:
结构体
Map
实现了Publisher
协议,因此它本身就是一个Publisher
init(upstream: Upstream, transform: @escaping (Upstream.Output) -> Output)
从它的初始化化函数来看,它需要传入一个upstream: Upstream
,这个upstream就是一个Publisher
,还需要传入一个闭包,闭包的参数是上游publisher的输出数据
Map
接收一个Publisher
作为输入,然后等待该publisher输出数据,然后把该数据映射成其他数据类型。
Subscription
Subscription
也是一个不容忽视的概念,是它连接了Publisher
和Subscriber
,我们看看它的代码:
public protocol Subscription : Cancellable, CustomCombineIdentifierConvertible {
/// Tells a publisher that it may send more values to the subscriber.
func request(_ demand: Subscribers.Demand)
}
同样,基于上边的代码,我们分析出以下几个信息:
它是一个协议,实现该协议的实例必须实现协议要求的方法
它继承了
Cancellable
协议,因此实现了Subscription
协议的实例自然就可以取消pipline使用
request
函数发送请求
事件过程
Publisher
收到订阅Publisher
调用Subscriber
的Subscriber/receive(subscription:)
方法返回一个subscription实例Subscriber
使用subscription发送requestPublisher
调用Subscriber
的Subscriber/receive(_:)
方法发送数据Publisher
调用Subscriber
的Subscriber/receive(completion:)
方法发送完成事件