Elastomeric 0.2.0

Elastomeric 0.2.0

Ivan Lesko 维护。



  • 作者
  • Christopher Cohen

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()