数据绑定的多种实现方法

想法

  • didSet 方法里,通知观察者
  • 支持多个观察者
  • 支持取下监听
  • 无需显式取消监听,在销毁时自动取消监听

代码

public final class Box<T> {public typealias Listenr = (T) -> Voidprivate var observers: NSHashTable<AnyObject>private var managerKey: Void?/// 真正存储的值public var value: T {didSet {observers.allObjects.forEach { (observer) inlet block = objc_getAssociatedObject(observer, &managerKey)if let block1 = block as? Listenr {block1(value)}}}}/// 初始化方法////// - Parameter value: 用来被绑定的valuepublic init(_ value: T) {self.value = valueobservers = 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)}}
}

几点说明

  • 使用了关联对象,把对监听对象的响应作为observer的一个属性。这样子,在observer销毁时,自然会取消监听
  • 使用了weak NSHashTable 来存储observers
  • 在初次绑定时,通知了observer当前值

使用例子

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

参考

  • MVVM in Practice - RWDevCon Session - raywenderlich.com

转载于:https://www.cnblogs.com/huahuahu/p/li-yong-shu-xing-guan-cha-qi-shi-xian-shu-ju-bang-.html

利用属性观察器实现数据绑定相关推荐

  1. 一起认识下浏览器的5种观察器

    "图片懒加载",这个词语想必大家再熟悉不过了.传统的实现方法是,监听scroll事件,获取img元素相对于视口的顶点位置el.getBoundingClientRect().top ...

  2. 技术图文:Python的属性装饰器详解

    背景 我们在以前的一篇图文 Python基础 – Task10. 类与对象 中介绍过利用property()方法既能保护类的封装特性,又能让开发者可以使用"对象.属性"的方式操作类 ...

  3. Adobe Reader 文档无法签名_手把手教你如何利用PDF阅读器压缩PDF文档

    众所周知,PDF格式文本.格式.字体.颜色.分辨率.链接及图形图像.声音.动态影像等所有的信息封装在一个特殊的整合文件中.这个优点也导致我们工作学习上接触到的PDF文档体积都不小,非常影响阅读体验和邮 ...

  4. DirectX11 With Windows SDK--17 利用几何着色器实现公告板效果

    DirectX11 With Windows SDK--17 利用几何着色器实现公告板效果 原文:DirectX11 With Windows SDK--17 利用几何着色器实现公告板效果 前言 上一 ...

  5. ssm影城项目_影场与属性访问器界面

    ssm影城项目 卡尔·迪亚(Carl Dea)最近跟踪了我的一篇名为" 保存内存"的博客文章! 为属性使用阴影字段 . 在他的博客中,他建议使用称为"属性访问器" ...

  6. threejs 影子属性_影子场vs.属性访问器接口第2轮

    threejs 影子属性 如果你们还没有注意到Dirk Lemmerman和我之间的(轻松) 摊牌 ,那么让我快速提及一下我们是如何做到这一点的. 首先,Dirk创建了JavaFX技巧23:" ...

  7. listview属性_属性提取器:获取ListView即时更新其元素的最佳方法

    listview属性 这篇文章是关于如何处理JavaFX ListViews和TableViews的,以及如何通过这些控件了解所包含元素的更改内容. 我想知道为什么在相关书籍中没有找到关于以下模式的任 ...

  8. 影场与属性访问器界面

    卡尔·迪亚(Carl Dea)最近跟踪了我的一篇名为" 保存内存"的博客文章! 为属性使用阴影字段 . 在他的博客中,他建议使用一个称为"属性访问器"的接口来消 ...

  9. 影子场vs.属性访问器接口第2轮

    如果你们还没有注意到Dirk Lemmerman和我之间的(轻松) 对决 ,那么让我快速提及一下我们是如何做到这一点的. 首先,Dirk创建了JavaFX技巧23:" 为属性保存内存阴影字段 ...

最新文章

  1. 获取本地 qt_好消息,可以使用 VS 进行 Qt 的跨平台开发啦!
  2. 【OpenCV】使用projectPoints实现透视图到俯视图的变化效果
  3. 59. 螺旋矩阵 II(模拟)
  4. 数据结构-栈之二进制转十进制和八进制
  5. react全局状态管理_rxv: 在React中用Vue3的reactivity包实现状态管理。
  6. auto.js小案例
  7. 计算机开机引导的结果是,电脑开机显示引导媒体是怎么回事
  8. python使用pkg包_Python deb-pkg-tools包_程序模块 - PyPI - Python中文网
  9. 使用CreateProcess函数运行其他程序
  10. 基于vue-cli 将webpack3 升级到 webpack4 配置
  11. js正则替换html字符串,js正则找出字符串的内容,并替换内容
  12. android 拼图小游戏
  13. iOS手势识别的工作原理
  14. 禁忌搜索算法(现代优化计算方法)
  15. C# 温故而知新:Stream篇(五)
  16. Linux 28 岁了,我们总结了 28 个不为人知的事实
  17. 实施MES系统的成功率只有50%,你知道为什么吗?
  18. AI高考的信息检索策略
  19. LearnOpenGL学习笔记—高级光照 09:SSAO
  20. 【软件设计师】知识点与试题

热门文章

  1. 2017 码云最火开源项目 TOP 50,你用过哪些?
  2. meshgrid 的使用方法
  3. 在线文档显示组件 FlexPaper
  4. RDL(C) Report Design Step by Step 2: SubReport
  5. c语言风景日历制作系统,初学,C语言日历制作
  6. 机器视觉系统中相机镜头选型技巧_工业相机在机器视觉系统中的地位和作用
  7. python读json文件太大github_GitHub上最火的开源项目是啥|JSON文件实战处理
  8. 一个寄存器有几个字节_STM32f103ZET6 学习资料 (连载2 寄存器的操作界限)
  9. Markdown--绘制流程图(flowchart)
  10. 设定pic单片机端口为输入_PIC单片机IO端口的软件/硬件可靠性使用方法讨论