Icon

RVS_GeneralObserver

描述

这是一组通用协议,旨在为基本的观察者模式实现提供一个简单的基础设施。

这是该项目的 GitHub 仓库。

这是该项目的主要文档。

不处理消息传递

该框架不处理观察者和被观察者之间的消息传递或通信管理。它只是为它们提供相互跟踪的基础设施。

有一些回调,明确与聚合管理相关,但除此之外,它只是一个提供可靠的关系图管理的工具。

由具体的实现来处理如何使用这些信息。

基于协议

该框架基于协议,而不是类或结构体。其中一些协议要求必须将其实现为类。协议默认实现被大量用于提供基础设施。

它解决了什么问题?

从本质上讲,任何观察者模式的实现实际上只是一个关系图。观察者订阅被观察者。被观察者使用订阅作为单向广播媒介。

管理订阅和关系对于该模式至关重要。如果我们不能信任我们的订阅列表,那么建立在其之上的所有东西都将面临风险。

与委托不同

Apple 在其许多 Cocoa 基础设施中使用 委托模式。这是一种出色而简单的模式,具有以下特性:

观察者(至少,我实现的方式)有不同的方面:

优点

管理订阅列表和关系是观察者模式的一个非常基本的部分,并且需要非常可靠。这就是开发此工具的原因。

我们甚至不应该考虑这个问题。

实现

Swift Package Manager (SPM):

仓库的 URI 是:

一旦你将该包包含在你的项目中(如果你想了解更多关于 SPM 的信息,你可能想 查看这个系列),你需要包含该库。它将是一个静态(构建时)库。

import RVS_GeneralObserver

Carthage:

你可以通过将以下行添加到你的 Cartfile 中来包含该库:

github "RiftValleySoftware/RVS_GeneralObserver"

你可能应该直接包含 Carthage/Checkouts/RVS_GeneralObserver/Sources/RVS_GeneralObserver/RVS_GeneralObserver_Protocols.swift 文件,而不是构建一个库。

Git 子模块 或直接文件下载

如果你想将该项目作为一个子模块包含,只需使用上面的 URI 之一(在 Swift Package Manager 部分)。最好直接从子模块包含 Sources/RVS_GeneralObserver/RVS_GeneralObserver_Protocols.swift 文件(无需模块导入)。

如果你只想下载并包含该文件,那么只需要处理一个文件。Sources/RVS_GeneralObserver/RVS_GeneralObserver_Protocols.swift 文件。

只需下载并包含该文件。无需导入模块。

被观察者

完成之后,你可以通过遵循 RVS_GeneralObservableProtocol 协议,使一个类(它需要是一个类)成为被观察者。

你需要在你的实现中创建两个存储属性(以下示例来自 单元测试):

class BaseObservable: RVS_GeneralObservableProtocol {
    /* ############################################################## */
    /**
    The required UUID. It is set up with an initializer, and left alone.
    */
    let uuid = UUID()
    
    /* ############################################################## */
    /**
    This is the required observers Array.
    */
    var observers: [RVS_GeneralObserverProtocol] = []

uuid 属性是一个“设置并忘记”的属性。只需完全按照上面的方法做,之后就不用担心它了。

observers 数组也是一个你不太可能直接使用的数组(但你可能会转换它)。它是跟踪订阅者的地方。这是你的被观察者将如何找到广播目标。通常,你可能会将其转换为更具体的类的数组,如下所示:

var castArray: [MySpecificSubscriberThatConformsToRVS_GeneralObserverProtocol] { observers as? [MySpecificSubscriberThatConformsToRVS_GeneralObserverProtocol] ?? [] }

观察者

我们有两种类型的观察者。一种是“通用”的,可以应用于 structclass,它不跟踪观察者订阅的被观察者;另一种是仅限 class 的变体,它跟踪观察者的订阅。

这些示例也来自 单元测试

标准(structclass)观察者:

struct BaseObserver: RVS_GeneralObserverProtocol {
    /* ############################################################## */
    /**
     The required UUID. It is set up with an initializer, and left alone.
     */
    let uuid = UUID()

仅限 class 的订阅跟踪观察者:

class SubTrackerObserver: RVS_GeneralObserverSubTrackerProtocol {
    /* ############################################################## */
    /**
     The required UUID. It is set up with an initializer, and left alone.
     */
    let uuid = UUID()
    
    /* ############################################################## */
    /**
     This is where we will track our subscriptions.
     */
    var subscriptions: [RVS_GeneralObservableProtocol] = []

由于协议默认实现使用引用数组,因此这应该是一个 class

订阅一个被观察者就像调用它的 subscribe() 方法一样简单,并提供观察者。

let subscribedObserver = observableInstance.subscribe(observerInstance)

如果订阅成功,则响应是 observerInstance。这允许该方法被链式调用。如果观察者已经被订阅,则可能为 nil。

取消订阅完全相同,只是这次我们调用 unsubscribe() 方法。

let unsubscribedObserver = observableInstance.unsubscribe(observerInstance)

还有 unsubscribeAll() 方法,用于 被观察者订阅跟踪观察者

调用这些方法将从一个被观察者实例中删除所有观察者,或者从一个观察者实例中删除所有被观察者。

回调

协议中没有任何必需的回调,但有一些非常基本的可选回调。

观察者协议在确认订阅时进行回调

func subscribedTo(_ observable: RVS_GeneralObservableProtocol)

以及在确认取消订阅时进行回调

func unsubscribedFrom(_ observable: RVS_GeneralObservableProtocol)

订阅跟踪协议有 几个内部方法,不应该被遵循协议的实例使用。

被观察者协议有一个可选回调

func observer(_ observer: RVS_GeneralObserverProtocol, didSubscribe: Bool)

当一个观察者订阅或取消订阅时(第二个参数表示这一点)会调用此回调。

一旦你设置好 class(或 struct),你就可以使用 observers 属性(被观察者)或 subscriptions 属性(观察者协议的订阅跟踪变体)来访问和与各种目标交互,并根据需要进行类型转换。

所有协议都有一个 amISubscribed() 布尔方法,你可以传入一个观察者(或被观察者)实例进行测试,以查看一个观察者是否订阅了一个被观察者。