美文网首页
Combine(一) Publisher和Subscriber

Combine(一) Publisher和Subscriber

作者: Joshua666 | 来源:发表于2019-10-21 15:58 被阅读0次

    1、Publisher被观察者

    Publisher是一个protocol,是Combine的核心;publisher可以向他的subscriber发送一个或多个values直到它发送了一个completion时间,这个completion可以是正常的结束,也可以是一个error。我们可以很简单的用一个array来创建一个publisher:

    let publisher = (1...5).publisher // b
    publisher.sink(receiveCompletion: { _ in // a
        print("completed")
    }, receiveValue: { val in
        print("value: \(val)")
    })
    // 输出
    value: 1
    value: 2
    value: 3
    value: 4
    value: 5
    completed
    

    a) .sink和.assign是两个为publisher绑定观察者的方法,观察者就像例子中的一样,是简单的closures来handle publisher发送出的值和结束事件。
    b) 用array创建出的publisher会将array中的元素一个一个的发送给观察者然后结束。注意:publisher只有在有观察者的情况下才会开始发送value

    而在上一篇文章中的Just就是一个特殊的Publisher,他只会发送一次然后自动结束

    let just = Just("Hello shit")
    just.sink(receiveCompletion: {
        _ in
        print("completed 111")
    }, receiveValue: {
        val in
        print("\(val) 111")
    })
    
    just.sink(receiveCompletion: {
        _ in
        print("completed222")
    }, receiveValue: {
        val in
        print("\(val) 222")
    })
    // 输出
    Hello shit 111
    completed 111
    Hello shit 222
    completed222
    

    2、Subject

    Subject也可以理解成特殊的Publisher,不同于publisher,subject可以用.send()来想subscriber发送values。先介绍两种常用的subjects:

    • PassthroughSubject - 可以持续向subscriber传输值或者结束事件,可以没有初始值
    • CurrentValueSubject - 初始化时必须有初始值,可以通过subject.value来查看当前publisher发送的值

    看完Subscriber一起给栗子

    3、Subscriber观察者

    上面的两个例子都是用了sink绑定了closures来作为观察者, 如果我们要自己定义subscriber,那就得遵循Subscriber protocol:

    class MySubscriber: Subscriber {
        typealias Input = Int // a
        typealias Failure = MyError // b
    
        func receive(completion: Subscribers.Completion<MyError>) { // c
            print("received completion")
        }
    
        func receive(_ input: Int) -> Subscribers.Demand { // d
            print("received value: \(input)")
            switch input {
            case 1:
                return .max(1) // e
            default:
                return .none // f
            }
        }
    
        func receive(subscription: Subscription) { // g
            subscription.request(.max(2)) // h
            print("subscription received")
        }
    }
    

    a) 接受的类型,这个必须和publisher的输出类型相等才行
    b) 错误类型,也需要和publisher会发出的error类型一样
    c) 当接收到publisher发出的结束事件之后要做的
    d) 当接收到publisher发出的值的时候要做的,注意这里返回了一个Subscribers.Demand意思是最多还能接受多少个values
    e) 把最多能接受values的个数+1
    f) 最多能接受values的个数不变
    g) 当订阅了publisher的时候执行,subscription.request可以定义初始接受values的个数

    let publisher = PassthroughSubject<Int, MyError>()
    let subscriber = MySubscriber()
    publisher.subscribe(subscriber)
    
    publisher.send(3)
    publisher.send(1)
    publisher.send(5)
    publisher.send(6)
    publisher.send(completion: .finished)
    //输出
    subscription received
    received value: 3
    received value: 1
    received value: 5
    received completion
    

    为啥没输出6呢?回去看看MySubscriber的定义就明白了

    相关文章

      网友评论

          本文标题:Combine(一) Publisher和Subscriber

          本文链接:https://www.haomeiwen.com/subject/uiytvctx.html