前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Combine 基本概念

Combine 基本概念

作者头像
小刀c
发布2022-09-21 16:21:33
2650
发布2022-09-21 16:21:33
举报
文章被收录于专栏:cc logcc log

Publisher

代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
public protocol Subscription: Cancellable, CustomCombineIdentifierconvertible {
    func request(_ demand: Subscribers.Demand)
}

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

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

自定义Subscriber

代码语言:javascript
复制
// 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
代码语言:javascript
复制
// 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

代码语言:javascript
复制
// 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
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-10-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Publisher
  • Subscriber
  • Subscription
  • 自定义Subscriber
  • Subject
    • PassthroughSubject
      • CurrentValueSubject
      • 类型抹除 Type erasure
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档