美文网首页
SwiftUI — Combine

SwiftUI — Combine

作者: 丿唯一的唯一丿 | 来源:发表于2020-02-22 23:56 被阅读0次

    @ObservedObject

    顾名思义来到了最关键的观察者模式

    观察者模式
    当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。
    意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
    主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。
    何时使用:一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。
    如何解决:使用面向对象技术,可以将这种依赖关系弱化。

    在 Combine 中,有几个重要的组成部分:
    发布者:Publiser
    订阅者:Subscriber
    操作符:Operator

    Publisher

    在 Combine 中,Publisher 相当于RxSwift中的 Observable,并且可以通过组合变换(Operator)重新生成新的 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
    
        /// This function is called to attach the specified `Subscriber` to this `Publisher` by `subscribe(_:)`
        ///
        /// - SeeAlso: `subscribe(_:)`
        /// - Parameters:
        ///     - subscriber: The subscriber to attach to this `Publisher`.
        ///                   once attached it can begin to receive values.
        func receive<S>(subscriber: S) where S : Subscriber, Self.Failure == S.Failure, Self.Output == S.Input
    }
    

    Combine提供了一个 enum Publishers,包括:

    struct Empty : 一个从不发布任何值的publisher,并且可以选择立即完成。
    struct Fail : 立即使用指定错误终止的publisher。
    struct Once: 只有一次向每个订阅者发布输出然后完成的publisher,或者在没有生成任何元素的情况下立即失败的publisher。
    struct Optional : 如果可选值具有值,则publisher仅向每个订阅者发布一次可选值。
    struct Sequence : 发布给定元素序列的publisher。
    struct Deferred : 在运行提供的闭包之前等待订阅的发布者,以便为新订阅者创建发布者
    

    Subscriber

    Subscriber相当于RxSwift中的Observer

    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 `Demand` instance indicating how many more elements the subcriber 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 `Completion` case indicating whether publishing completed normally or with an error.
        func receive(completion: Subscribers.Completion<Self.Failure>)
    }
    

    可以看出,Publisher 在自身状态改变时,调用 Subscriber 的三个不同方法(receive(subscription), receive(_:Input), receive(completion:))来通知 Subscriber。

    这里也可以看出,Publisher 发出的通知有三种类型:

    Subscription:Subscriber 成功订阅的消息,只会发送一次,取消订阅会调用它的 Cancel 方法来释放资源
    Value(Subscriber 的 Input,Publisher 中的 Output):真正的数据,可能发送 0 次或多次
    Completion:数据流终止的消息,包含两种类型:.finished 和 .failure(Error),最多发送一次,一旦发送了终止消息,这个数据流就断开了,当然有的数据流可能永远没有终止
    大部分场景下我们主要关心的是后两种消息,即数据流的更新和终止。

    Combine 内置的 Subscriber 有三种:
    Sink
    Assign
    Subject
    Sink 是非常通用的 Subscriber,我们可以自由的处理数据流的状态。

    let once: Publishers.Once<Int, Never> = Publishers.Once(100)
    let observer: Subscribers.Sink<Int,Never> = Subscribers.Sink(receiveCompletion: {
        print("completed: \($0)")
    }, receiveValue: {
        print("received value: \($0)")
    })
    once.subscribe(observer)
    

    Assign 可以很方便地将接收到的值通过 KeyPath 设置到指定的 Class 上(不支持 Struct)
    一旦 publisher 的值发生改变,相应的,student 的 score 也会被更新。
    PassthroughSubject 这里是 Combine 内置的一个 Publisher。

    Subject

    有些时候我们想随时在 Publisher 插入值来通知订阅者,在 Rx 中也提供了一个 Subject 类型来实现。Subject 通常是一个中间代理,即可以作为 Publisher,也可以作为 Subscriber。Subject 的定义如下:

    public protocol Subject : AnyObject, Publisher {
    
        /// Sends a value to the subscriber.
        ///
        /// - Parameter value: The value to send.
        func send(_ value: Self.Output)
    
        /// Sends a completion signal to the subscriber.
        ///
        /// - Parameter completion: A `Completion` instance which indicates whether publishing has finished normally or failed with an error.
        func send(completion: Subscribers.Completion<Self.Failure>)
    }
    

    作为 Subscriber 的时候,可以通过 Publisher 的 subscribe(_:Subject) 方法订阅某个 Publisher。

    作为 Publisher 的时候,可以主动通过 Subject 的两个 send 方法,我们可以在数据流中随时插入数据。目前在 Combine 中,有三个已经实现对 Subject: AnySubject,CurrentValueSubject 和 PassthroughSubject 。

    CurrentValueSubject : 包含单个值并且当值改变时发布新元素的subject

    相关文章

      网友评论

          本文标题:SwiftUI — Combine

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