因果律 0.0.4

因果律 0.0.4

Danny Sung 维护。



因果律 0.0.4

  • 作者:
  • dannys42

build status macOS iOS Linux Apache 2

Causality

Causality 是一个简单的线程安全的 Swift 内存总线,它支持完全类型的 Event 和 State。

此外,Causality 还提供了监控 State 信息的功能。StateEvent 类似,但存在以下区别:

  • State 处理器将立即接收最后一个已知的好值(如果有的话)
  • 当状态值与上一个值相同时不调用 State 处理器
  • 而一个 Event 有一个关联的 Message,一个 State 有一个关联的 Value
  • 状态值的 Value 必须符合 Equatable 协议。

安装

Swift 包管理器

Causality 包添加到您的应用程序 Package.swift 文件中的依赖项中。用最新的 Causality 发行版 替换 "x.y.z"。

.package(url: "https://github.com/dannys42/Causality.git", from: "x.y.z")

Causality 添加到目标依赖中

.target(name: "example", dependencies: ["Causality"]),

CocoaPods

Causality 添加到您的 Podfile 中

pod `Causality`

使用方法

事件

只是一个事件(没有数据)

最简单的事件管理没有关联数据。

声明事件

这声明了一个名为aTriggerEvent的事件,并且没有关联数据。

struct MyEvents {
    static let aTriggerEvent = Causality.Event<Causality.NoMessage>(label: "A Trigger")
}

订阅事件

要订阅此事件

let subscription = Causality.bus.subscribe(MyEvents.aTriggerEvent) { _ in
    print("Event was triggered")
}

发布事件

要发布/发布此类型的事件

Causality.bus.publish(MyEvents.aTriggerEvent)

带有关联数据的事件

事件可以包括任何类型的数据(称为消息)。事件标签完全类型指定了消息。因此,订阅者将能够为其处理器提供完全类型化的消息。

定义消息

消息可以是标准的Swift类型,如IntString等。它也可以是一个遵循Causality.Messagestructclass。请注意,对于消息,您想要值语义还是引用语义。一般来说,值语义(即struct)会更安全。在这个例子中,我们将声明一个struct

struct InterestingMessage: Causality.Message {
    let string: String
    let number: Int
}

声明事件

事件可以被声明为具有相关的消息。如果已声明,消息是发布事件时必需的类型参数。并且同样地,它将被作为类型参数提供给事件的订阅者。

声明带有消息的事件

let MyInterestingEvent = Causality.Event<SomeMessage>(label: "Some Event")
let MyStringEvent = Causality.Event<String>(label: "An event with a String message")
let MyNumberEvent = Causality.Event<Int>(label: "An event with an Int message")

或对事件进行分类

struct MyEvents {
    static let MyInterestingEvent = Causality.Event<InterestingMessage>(label: "An interesting Event 1")
    static let MyStringEvent = Causality.Event<String>(label: "An event with a String message")
    static let MyNumberEvent = Causality.Event<Int>(label: "An event with an Int message")
}

订阅和取消订阅事件

保存您的订阅,以便稍后取消订阅

let subscription = Causality.bus.subscribe(MyEvents.MyInterestingEvent) { interestingMessage in
    print("A message from MyInterestingEvent: \(interestingMessage)")
}

Casaulity.bus.unsubscribe(subscription)

或在订阅处理程序内部取消订阅。以下是一个一次性事件处理器的示例

Causality.bus.subscribe(MyEvents.MyStringEvent) { subscription, string in
    print("A string from MyStringEvent: \(string)")
    
    subscription.unsubscribe()
}

发布事件

要发布/发布事件

Causality.bus.publish(MyEvents.MyInterestingEvent, 
    message: InterestingMessage(string: "Hello", number: 42))

事件总线

总线别名

为您的总线创建别名

let eventBus = Causality.bus

eventBus.publish(MyEvents.MyInterestingEvent, 
    message: InterestingMessage(string: "Hello", number: 42))

本地总线

或者创建本地总线以隔离您的事件

let newEventBus = Causality.Bus(label: "My local bus")

newEventBus.publish(MyEvents.interestingEvent, 
    message: InterestingMessage(string: "Hello", number: 42))

状态

定义状态值

类似于一个 事件,一个 状态 带有一个关联的 。值可以是原始类型,如 IntString 等。或者它们可以是 structclass。 (类似于一个事件 消息,您通常会想使用一个 struct。)然而,一个 必须遵守 Equatable

struct PlayerInfo: Causality.StateValue {
    let numberOfLives: Int
    let health: Int
    let armor: Int
}

声明状态

声明带有关联值的状态

let playerState = Causality.State<PlayerInfo>(label: "Player State")

或者对您的状态进行分类

struct GameStates {
    static let playerState1 = Causality.State<PlayerInfo>(label: "Player 1 State")
    static let playerState2 = Causality.State<PlayerInfo>(label: "Player 2 State")
}

订阅和取消订阅状态变更

保存您的订阅,以便稍后取消订阅

let subscription = Causality.bus.subscribe(GameStates.playerState1) { state in
    print("Player 1 state changed to: \(state)")
}

Casaulity.bus.unsubscribe(subscription)

或从订阅处理程序中取消订阅。以下示例将仅监视单个状态变更

Causality.bus.subscribe(GameStates.playerState1) { subscription, message in
    print("Player 1 state changed to: \(state)")
    
    subscription.unsubscribe()
}

如果状态之前已经被设置,订阅处理程序将立即调用上一次已知的值。只有随后的 .set() 调用具有不同的值时,订阅处理程序才会被调用。

设置状态

Causality.bus.set(GameStates.playerState1, 
    value: PlayerInfo(numberOfLives: 3, health: 75, armor: 10))

动态状态

在上面的游戏示例中,我们为每个状态有一个 Causality.State 变量。但如果我们有“n”个玩家呢?在这种情况下,我们可以使用动态状态。动态状态允许您参数化您的状态。动态状态是 Codable 的,并要求您定义 CodingKeys 和重载 encode() 函数以指定“键”参数。这些参数用于唯一标识状态。例如

class PlayerState<Value: PlayerInfo>: Causality.DynamicState<Value> {
    let playerId: Int

    init(playerId: Int) {
        self.playerId = playerId
    }
    enum CodingKeys: CodingKey {
        case playerId
    }
    override func encode(to encoder: Encoder) throws {
        try super.encode(to: encoder)
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(self.playerId, forKey: .playerId)
    }
}

现在来订阅

Causality.bus.subscribe(PlayerState<PlayerInfo>(playerId: 1)) { subscription, playerInfo in
    print("Current player info is: \(playerInfo))
}

或者添加更多组织

struct GameState {
    static func playerState(_ playerId: Int) -> PlayerState<PlayerInfo> {
        return PlayerState<PlayerInfo>(playerId: playerId)
    }
}

Causality.bus.subscribe(GameState.playerState(1)) { subscription, playerInfo in
    print("Current player info is: \(playerInfo)")
}

并设置/更新状态

Causality.bus.set(state: GameState.playerState(1), 
                  value: PlayerInfo(
                            numberOfLines: 3,
                            health: 75,
                            armor: 100))

同样,您可以考虑使用 IntString 等基本类型作为 Value

let UserNameState = Causality.State<String>(label: "user name state")
Causality.bus.subscribe(UserNameState) { username in
    print("Username is now: \(username)")
}
Causality.bus.set(UserNameState, "Mary Jane Doe")

动态事件

可以通过以类似的方式定义它们来参数化事件

class MyEvent<Message: Causality.Message>: Causality.DynamicEvent<Message> {

    let eventId: Int

    init(eventId: Int) {
        self.eventId = eventId
    }
    enum CodingKeys: CodingKey {
        case eventId
    }
    override func encode(to encoder: Encoder) throws {
        try super.encode(to: encoder)
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(self.eventId, forKey: .eventId)
    }
}

然后创建事件

struct MyEvents {
    static func event(_ eventId: Int) -> MyEvent<InterestingMessage> {
        return MyEvent<InterestingMessage>(eventId: eventId)
    }
}

订阅事件

let subscription = Causality.bus.subscribe(MyEvents.event(1)) { subscription, message in
    print("A message from event \(subscription.event.eventId): \(message)")
}

并发布事件

Causality.bus.publish(MyEvents.event(1), 
    message: InterestingMessage(string: "Hello", number: 42))

API 文档

更多信息请访问我们的 API 参考

相关项目

许可证

该库遵循Apache 2.0许可。完整的许可证文本可以在LICENSE中获取。