Elastomeric
Elastomeric
是一个简单的异步响应式机制,旨在便于 UI 状态的实现。 Elastomeric
对于在文件之间存储和读取任何数据类型非常有用,无需使用层的类变量。
使用方法
声明
您的应用应该在 Elastomer
上声明一个 extension
,其中包含静态变量的
//Elastomer declarations
extension Elastomer {
static var someBool:Elastomer { return Elastomer(associatedType: Bool.self, name: "someBool") }
static var someString:Elastomer { return Elastomer(associatedType: String.self, name: "someString") }
static var someInt:Elastomer { return Elastomer(associatedType: Int.self, name: "someInt") }
}
相等性(自定义类型)
一种类型必须实现 Equatable
协议才能与 Elastomer
关联。有时传输基本数据类型不足以满足应用的需求。
struct FilterVCPresentation: Equatable {
var indexPath: IndexPath?
var isPresented: Bool
static func == (lhs: FilterVCPresentation, rhs: FilterVCPresentation) -> Bool {
if let lhsIndexUnwrapped = lhs.indexPath {
if let rhsIndexUnwrapped = rhs.indexPath {
if (lhsIndexUnwrapped == rhsIndexUnwrapped) && (lhs.isPresented == rhs.isPresented) {
return true
}
}
}
return false
}
}
暂存值(写入)
通过对任何 Elastomer
调用 .stageValue(_:)
来设置新值(也称为预存)。当对新值进行预存时,所有注册到特定 Elastomer
上以监听新值的观察者都将被通知。
// 1. Add or change a value on a per-value basis
Elastomer.someBool.stageValue(true)
Elastomer.someString.stageValue("hello!")
Elastomer.someInt.stageValue(Int(27))
// 2. All Attempts to stage a value of an unassociated type will be ignored.
Elastomer.someInt.stageValue(Float(27))
// 3. A value may be staged after an arbitrary delay
Elastomer.someBool.stageValue(false, afterDelay: TimeInterval(12))
// 4. Redundant entries are ignored by default, but that may be overridden
Elastomer.someBool.stageValue(false, discardingRedundancy: false)
// 5. Values may be staged in a batch operation
[Elastomer.someBool:true, Elastomer.someInt:Int(72), Elastomer.someString:"goodbye!"].stage()
表达值(读取)
通过在任意 Elastomer
上调用 .expressValue { }
来读取当前值(也称为表达)。值将异步传递。可选地将值转换为您期望的类型。
// 1. Recall value from model. Response will be deivered in a trailing closure
Elastomer.someBool.expressValue { (value) in
//Cast optional Any? as Bool
guard let bool = value as? Bool else { return }
//Print result
print("Boolean derived from value in closure \(bool)")
}
// 2. Recall multiple values from the model at once
[Elastomer.someBool, Elastomer.someString, Elastomer.someInt].expressValues { (dict) in
//The dictionary contains Elastomer-value associations
guard let bool = dict[Elastomer.someBool] as? Bool else { return }
//Print result
print("Boolean derived from value subscripted from dictionary \(bool)")
}
观察值
任何对象都可以注册为任何 Elastomer
的观察者(或一组 Elastomer
)。每次将新值存储到 Elastomer
中时,都会调用所有观察块。
// 1. Observe any mutations to the Elastomer-associated data
let _ = Elastomer.someBool.registerObserver { (mutation) in
//The new value can be derived from the mutation
guard let newBool = mutation.newValue as? Bool else { return }
//The previous value can be derived from the mutation
guard let oldBool = mutation.oldValue as? Bool else { return }
//A timestamp of the change is also delivered by way of the mutation
let timeOfMutation:TimeInterval = mutation.timestamp
//Print contents of mutation
print("old value \(oldBool) was replaced by new value \(newBool), \(abs(CACurrentMediaTime()-timeOfMutation)) seconds ago")
}
// 2. New observers will return UUD receipts that can be captured for later retirement
let stringObserverReceipt = Elastomer.someString.registerObserver { (mutation) in
print("The string did change")
}
// 3. An observer may be retired with the associated receipt
Elastomer.someString.retireObserver(stringObserverReceipt)
// 4. New observers may be registered in batches
let receipts = [Elastomer.someString, Elastomer.someInt].registerObservers { (mutation) in
switch mutation.elastomer {
case .someString: print("The string did change")
case .someInt: print("The int did change")
default: break
}
}
// 5. A dictionary of observer receipts may be retired together
receipts.retireAll()
发布
Elastomer
可以通过调用 .post()
来告知所有观察者,而无需改变其底层值(通过 .stageValue(_:)
调用)。
// Notifies all observer blocks
Elastomer.someBool.post()