一,概念

  观察者(Observer)模式又名发布-订阅(Publish/Subscribe)模式。GOF给观察者模式如下定义:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

二,类图

  观察者模式本质上时一种发布-订阅模型,用以消除具有不同行为的对象之间的耦合,通过这一模式,不同对象可以协同工作,同时它们也可以被复用于其他地方Observer从Subject订阅通知,ConcreteObserver实现重现ObServer并将其重载其update方法。一旦SubJect的实例需要通知Observer任何新的变更,Subject会发送update消息来通知存储在其内部类中所注册的Observer、在ConcreteObserverupdate方法的实际实现中,Subject的内部状态可被取得并进行后续处理。
 
三,代码展示
这里就不再具体实现了,iOS中常用的有广播通知,和KVO都是观察者模式,下面用代码展示下

notification

广播,感兴趣可以了解下java中的观察者实现原理,如出一辙。java可以看的源码。

1注册与注销广播

deinit {
NotificationCenter.default.removeObserver(self)
} required init(coder aCoder: NSCoder) {
super.init(coder: aCoder)!
} override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(changeColor(notf:)), name: NSNotification.Name(rawValue: kChangeBackgroundColour), object: nil) } @objc func changeColor(notf: Notification) {
self.view.backgroundColor = notf.userInfo?["bg_color"] as? UIColor;
}

2发送广播

@IBAction func changeToRed(_ sender: Any) {
NotificationCenter.default.post(name: NSNotification.Name(rawValue: kChangeBackgroundColour), object: nil, userInfo: ["bg_color": UIColor.red])
}

KVO:

只有 NSObject 才能支持 KVO。

Swift 4中的一个对此有影响的改变是继承 NSObject 的 swift class 不再默认全部 bridge 到 OC。然而 KVO 又是一个纯 OC 的特性,所以如果是 swift class 需要在声明的时候增加 @objcMembers 关键字。否则在运行的时候你会得到一个 error:

fatal error: Could not extract a String from KeyPath
Swift.ReferenceWritableKeyPath

另外一件事就是被观察的属性需要用dynamic修饰,否则也无法观察到。

一个好消息是不需要在对象被回收时手动 remove observer。但是这也带来了另外一个容易被忽略的事情:观察的闭包没有被强引用,需要我们自己添加引用,否则当前函数离开后这个观察闭包就会被回收了。

@objcMembers class OCClass: NSObject {
dynamic var name: String init(name: String) {
self.name = name
}
} class ViewController: UIViewController { var swiftClass: OCClass!
var ob: NSKeyValueObservation! override func viewDidLoad() {
super.viewDidLoad() swiftClass = OCClass(name: "oc")
ob = swiftClass.observe(\.name) { (ob, changed) in
let new = ob.name
print(new)
}
swiftClass.name = "swift4"
}
}

KVO 之后返回的是一个 NSKeyValueObservation 实例,需要自己控制这个实例的生命周期。

最新文章

  1. 一维码:EAN-13码的识别
  2. C++ 自动指针 共享指针
  3. DotNetBar v12.6.0.4 Fully Cracked
  4. Json格式理解
  5. QT正则表达式
  6. LoadRunner获取一个独特的价值在执行的场景
  7. 老李推荐:第8章7节《MonkeyRunner源码剖析》MonkeyRunner启动运行过程-小结
  8. [转]移动前端开发之viewport的深入理解
  9. Unity资源内存管理--webstream控制
  10. python学习笔记——(一)基础设置
  11. C# 耗时统计
  12. Java SE之向上转型(动态绑定)与向下转型
  13. linux中fork函数详解(转)
  14. oracle 用一个表的一个字段更新另一个表的一个字段
  15. inline-block各浏览器兼容以及水平间隙问题解决方案
  16. SpringBoot入门篇--对于JSON数据的返回以及处理一
  17. 利用InfoPath实现SharePoint Server 2013列表的级联选择(Cascading Drop Down List)
  18. SpringMVC中配置AOP拦截controller 失效
  19. Redis客户端基本命令
  20. UVa 1218 - Perfect Service(树形DP)

热门文章

  1. 如何使用Visual Studio 2008(VS2008)编译C语言
  2. Couchbase III(Python Library)
  3. mongodb 的创建和使用
  4. CactiI表结构和数据被动获取
  5. python021 Python3 错误和异常
  6. asp.net mvc数据验证
  7. BZOJ4373 算术天才与等差数列 题解
  8. bzoj 4736 /uoj274【清华集训2016】温暖会指引我们前行 lct
  9. bzoj 1702 贪心,前缀和
  10. Codeforces917D. Stranger Trees