hiccLoghicc log by wccHipo日志

Combine 基本概念

Publisher#

public protocol Publisher { // 1 associatedtype Output // 2 associatedtype failure: Error // 4 func receive<S>(subscriber: S) where S: Subscriber, Self.Failure == S.Failure, Self.Output == S.Input } extension Publisher { // 3 public func subscribe<S>(_ subscriber: S) where S: Subscriber, Self.Failure == S.Failure, Self.Output == S.Input }
  1. Publisher 产生数据的类型
  2. Publisher可能产生错误的类型,如果能够保证一定不出错,使用Never
  3. 订阅者,可以使用subscribe(-:)来接受消息
  4. 实现subscribe(-:)需要调用receive(subscriber:)来将订阅者订阅到publisher

Subscriber#

public protocol Subscriber: CustomCombineIdentifierConvertible { // 1 associatedtype Input // 2 associatedtype Failure: Error // 3 func receive(subscription: Subscription) // 4 func receive(_ input: Self.Input) -> Subscribers.Demand // 5 func receive(completion: Subscribers.Completion<Self.Failure>) }
  1. 订阅者接收到的值得类型
  2. 订阅者可能接受到的错误信息,如果Publisher不会出错,则是Never
  3. Publisher会调用receive(subscription:)来传递 subscription
  4. Publisher调用receive(_:)来传值。
  5. Publisher调用receive(completion:),在结束或者出错时候。

Subscription#

public protocol Subscription: Cancellable, CustomCombineIdentifierconvertible { func request(_ demand: Subscribers.Demand) }

订阅者调用request(_:_)来告知愿意接受更多的值,从一个最大的值,到无限制。

  • subscription.request背压 backpressure mmanagement
  • Subscriber.receive(_:_)可以在每次接收到值时候调整,表示后续要接受的数量
  • Subscriber.receive(_:_)调整的值是增量的,也就是说不能是负数(否则会返回fatalError)。

自定义Subscriber#

// 1 let publisher = (1...6).publisher // 2 final class IntSubscriber: Subscriber { // 3 typealias Input = Int typealias Failuse = Never // 4 func reveive(subscription: Subscription) { subscription.request(.max(3)) }     // 5 func receive(_ input: Int) -> Subscribers.Demand { print("Recevied value", input) // return .unlimited return .none // 等于 .max(0) } // 6 func receive(completion: Subscribers.Completion<Never>) { print("Received completion", completion) } }

Subject#

PassthroughSubject#

CurrentValueSubject#

// 1 var subscriptions = Set<AnyCancellable>() // 2 let subject = CurrentValueSubject<Int, Never>(0) // 3 subject .sink(receiveValue: {print($0)}) .store(in: &subscriptions) // 4
  • 第四步,把subscription保存在subscriptions中,通过inout参数引用而不是拷贝的方式来传递。
  • 通过subject.value的方式来获取值
  • 通过subject.value = 3赋值,或者subject.send(1)方式来发送事件
  • 注意:只能subject.send(completion: .finished)来结束事件。

类型抹除 Type erasure#

// 1 let subject = PassthroughSubject<Int, Never> // 2 let publisher = subject.eraseToAnyPublisher() // 3 publisher .sink(receiveValue {print($0)}) .store(in: &subscriptions) // 4 subject.send(0)
  • 类型抹除后publisher, 变成了anyPublisher<Int, Never>,后续的就不会知道具体的类型和细节
  • 不再有send方法,
  • 后续写文章,可以尝试自己实现marble diagrams