简单、轻量且实用的 Swift 事件库。
Eventful-Swift 是一个用于轻量级事件分发与处理的 Swift 库。通过遵守 EventDispatcher
协议,类或结构体可以定义各种事件(通过 Event<T>
或 EventRef<T>
),可以被监听并进行反应。这个库还在 开发中。
您也可以将源文件手动添加到项目中。
Eventful-Swift/
子目录中的所有 Swift 文件添加到您的项目中使用 Event<T>
或 EventRef<T>
,您可以轻松地将基于 动作 到 反应 的事件处理添加到现有代码中。
class Person: EventDispatcher {
var name: String
var age: Int
var event_died = EventRef<Bool>()
func removeEventListeners() {
self.event_died.removeListeners()
}
init(name: String, age: Int) {
self.name = name
self.age = age
}
deinit {
self.event_died.dispatch(true)
}
}
在上面的示例中,Person
类遵守了 EventDispatcher
协议,并定义了一个事件:当 Person
实例将要被销毁时调用的 event_died
。事件是 EventRef<T>
类型,其中 T
是一个泛型类型,表示将传递回事件监听器的值。
您可以创建您的事件为 Event<T>
类型 - 这是一个结构体。或者 EventRef<T>
类型 - 这是一个类。这取决于您的具体情况。在底层,EventRef<T>
类持有一个私有的 Event<T>
结构体,并将所有调用转发给它。
通过调用它的 dispatch(value: T)
函数来分发事件,并将要返回到事件监听器的值传递进去。
监听并反应到事件就像分发它们一样简单。您只需作为监听器进行注册并分配一个 反应 闭包。
var person: Person? = Person(name: "Bob", age: 23)
person?.event_died.addListener { (value: Bool) in
print("Bob died 😭")
}
print("\(person?.name) was born 😄")
print("\(person?.name) is living his life...")
person = nil
控制台输出将显示
Bob was born 😄
Bob is living his life...
Bob died 😭
在上面的示例中,我们向人物的 died
事件添加了一个监听器。当事件被分发时,我们简单地打印了 Bob died 😭
到控制台。
就像添加事件监听器一样,我们也可以移除它们。`addListener` 函数实际上是定义为:addListener(handler: (T) -> ()) -> EventToken
。它返回一个 EventToken
,之后可以用它来从事件中移除监听器。上面的示例可以修改来演示这一点
var person: Person? = Person(name: "Bob", age: 23)
let eventToken = person?.event_died.addListener { (value: Bool) in
print("Bob died 😭")
}
print("\(person?.name) was born 😄")
print("\(person?.name) is living his life...")
person = nil
person?.event_died.removeListener(token: eventToken)
另外,也可以通过调用事件的 removeListeners()
函数来移除特定事件的全部监听器。EventDispatcher
协议还要求在任何一个事件生成实体中实现 removeEventListeners()
函数。因此,可以通过调用 removeEventListeners()
来移除所有事件的全部监听器 - 假设事件生成实体已经正确实现了该函数。
// Removes all listeners for a specific event
person?.event_died.removeListeners()
// Removes all listeners for every event on an entity
person?.removeEventListeners()
EventfulValue
类型是一个自定义的 EventDispatcher
,在它内部值将要改变时以及值成功改变后都会分发事件。简单来说,它是一个小巧的值包裹器,模拟 KVO 值变更。EventfulValue
定义了两个事件
event_willChangeValue
event_didChangeValue
var greeting = EventfulValue("Hello")
greeting.event_didChangeValue.addListener { (info: EventfulValueInfo)
print("greeting: didChangeValue - was: \"\(info.oldValue)\", now: \"\(info.newValue)\"")
}
greeting.set("Bonjour")
这将把 greeting
的值设置为 "Bonjour",并触发变量的 didChangeValue
事件。注意闭包提供了 EventfulValueInfo
类型的变量。这是一个结构体,包含变化变量的旧值和新值。
因为 EventfulValue
类型“包装”实际的值用于事件处理,简单的 set/get 语句将无法工作。相反,必须直接通过 value
成员访问其底层值。还可以使用 get() -> T
或 set(value: T)
函数。
var x = EventfulValue(7)
// Will not work:
x = 13
// Will work:
x.value = 13
x.set(23)
let xValue = x.get()
print("value of x is \(xValue)")
手动键入 EventfulValue
并访问底层 value
成员可能会很麻烦。幸运的是,还有一个初始化、修改和检索此值的简写语法。
// These are all valid ways to initialize an EventfulValue
var x = EventfulValue(10)
var y = ~("Hello, world!")
var z = ~[1, 2, 3]
// EventfulValue's can be modified by using the '~>>' operator
x ~>> 13
y ~>> "Hola!"
z ~>> [4, 5, 6]
// An EventfulValue's value member can be accessed via a postfix '~'
let xValue = x~
let yValue = y~
print("value of z is \(z~)")
可以通过在值前加一个波浪号(~
)来初始化一个 EventfulValue
。还可以选择用括号包围这个值。使用 ~>>
赋值运算符可以直接将值赋给 EventfulValue
的底层 value
成员。最后,可以通过后缀波浪号(~
)直接访问底层 value
成员。
EventfulValue
索引。这将使处理元组、数组和字典变得更容易。EventDispatcher
类。