其他分享
首页 > 其他分享> > 利用属性观察器实现数据绑定

利用属性观察器实现数据绑定

作者:互联网

利用属性观察器实现数据绑定

数据绑定的多种实现方法

数据绑定实现方法

想法

代码

public final class Box<T> {
    public typealias Listenr = (T) -> Void

    private var observers: NSHashTable<AnyObject>
    private var managerKey: Void?

    /// 真正存储的值
    public var value: T {
        didSet {
            observers.allObjects.forEach { (observer) in
                let block = objc_getAssociatedObject(observer, &managerKey)
                if let block1 = block as? Listenr {
                    block1(value)
                }
            }
        }
    }

    /// 初始化方法
    ///
    /// - Parameter value: 用来被绑定的value
    public init(_ value: T) {
        self.value = value
        observers = NSHashTable<AnyObject>.weakObjects()
    }


    /// 添加观察者。target在销毁时,会自动移除观察,不会有内存泄漏。
    ///
    /// - Parameters:
    ///   - target: 观察者,变化时,会通知到它
    ///   - block: 发生变化时,需要执行的操作。block为nil,取消绑定
    public func bind(target: AnyObject, block: Listenr?) {
        observers.add(target)
        objc_setAssociatedObject(target, &managerKey, block, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        block?(value)
        if block == nil {
            observers.remove(target)
        }
    }
}

几点说明

使用例子

        let box = Box<Int>.init(4)
        let observer2 = ObserverExample.init()
        let observer3 = ObserverExample.init()
        box.bind(target: observer2) { [unowned observer2 ] (value) in
            observer2.value = value
        }
        box.bind(target: observer3) { [unowned observer3 ] (value) in
            observer3.value = value
        }
        
        // 去掉 observer2 对box 的监听
        box.bind(target: observer2, block: nil)
        box.value = -9
        XCTAssertEqual(box.value, observer3.value)
        XCTAssertNotEqual(box.value, observer2.value)

参考

posted on 2019-01-19 09:32  花老????  阅读(94)  评论(0)  编辑  收藏

标签:观察器,box,target,绑定,value,observers,observer2,block,属性
来源: https://blog.51cto.com/u_15223551/2834073