在Swift中使用KVO,有如下两种方法:

原OC提供的:

open func addObserver(_ observer: NSObject, forKeyPath keyPath: String, options: NSKeyValueObservingOptions = [], context: UnsafeMutableRawPointer?)

@available(iOS 5.0, *)
open func removeObserver(_ observer: NSObject, forKeyPath keyPath: String, context: UnsafeMutableRawPointer?) open func removeObserver(_ observer: NSObject, forKeyPath keyPath: String)

使用上面提供的方法实现KVO,需要注意一点,keyPath对应的属性,必须要是OC的属性,如果是通过swift定义的属性,必须在属性前添加@objcdynamic修饰才可以,否则KVO将无效果,如下:

class ViewController: UIViewController {

    // swift定义的属性,必须使用@objc和dynamic标注,否则kvo将无效果
@objc dynamic var name: String = "" override func viewDidLoad() {
super.viewDidLoad()
// 添加KVO
addObserver(self, forKeyPath: "name", options: [.new], context: nil) // 修改name值
name = "drbox"
} override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
print("kvo: name: \(change?[.newKey] as? String ?? "")")
}
}

swift提供的:

func observe<Value>(_ keyPath: KeyPath<ViewController, Value>, options: NSKeyValueObservingOptions = [], changeHandler: @escaping (ViewController, NSKeyValueObservedChange<Value>) -> Void) -> NSKeyValueObservation

使用上面提供的方法实现KVO,注意事项同上,代码如下:

class ViewController: UIViewController {

    // swift定义的属性,必须使用@objc和dynamic标注,否则kvo将无效果
@objc dynamic var name: String = ""
var obs: NSKeyValueObservation? deinit {
// 移除观察者
obs = nil
} override func viewDidLoad() {
super.viewDidLoad() // 添加kvo
obs = observe(\.name, options: [.new], changeHandler: { (_, change) in
print("name: \(change.newValue ?? "")")
}) name = "drbox" } }

使用过rxswift都知道,它同样提供了KVO的实现,实现原理实际上就是对OC的KVO的封装,因此在使用时同样要注意以上事项:@objc dynamic

class ViewController: UIViewController {

    @objc dynamic var name: String = ""
var disposeBag = DisposeBag() override func viewDidLoad() {
super.viewDidLoad() // 方法一:
rx.observe(\.name).bind { str in
print("name1: \(str)")
}.disposed(by: disposeBag)
// 方法二:
rx.observe(String.self, "name").map({ $0 ?? ""}).bind { str in
print("name2: \(str)")
}.disposed(by: disposeBag)
// 方法三:
rx.observeWeakly(String.self, "name").map({ $0 ?? ""}).bind { str in
print("weak name: \(str)")
}.disposed(by: disposeBag) name = "drbox" } }

其中rx.observe与rx.observeWeakly的区别在于前者返回的Observable会对观察者target强持有(strong);后者返回的Observable会对target弱持有(weak)

具体的比较如下:

性能比较:

  • rx.observe 更加高效,因为它是一个 KVO 机制的简单封装。
  • rx.observeWeakly 执行效率要低一些,因为它要处理对象的释放防止弱引用(对象的 dealloc 关系)。

使用场景比较:

  • 在可以使用 rx.observe 的地方都可以使用 rx.observeWeakly。
  • 使用 rx.observe 时路径只能包括 strong 属性,否则就会有系统崩溃的风险。而 rx.observeWeakly 可以用在 weak 属性上。

当然rx.observe也可以决定其返回的Observable是否强持有target,可以设置参数:retainSelf,默认:true(强持有)

// retainSelf
rx.observe(String.self, "name", retainSelf: true).map({ $0 ?? ""}).bind { str in
print("name2: \(str)")
}.disposed(by: disposeBag)

Swift中使用KVO的更多相关文章

  1. how to use kvo with swift (怎样在swift中使用kvo)

  2. 一览Swift中的常用关键字

    要学习Swift这门语言,就必须先了解Swift的关键字及对应的解释.这里就列一下在Swift中常用到的关键字. 关键字是类似于标识符的保留字符序列,除非用重音符号(`)将其括起来,否则不能用作标识符 ...

  3. Swift 中枚举

    Swift 中枚举高级用法及实践 字数11017 阅读479 评论0 喜欢20 title: "Swift 中枚举高级用法及实践"date: 2015-11-20tags: [AP ...

  4. Combine 框架,从0到1 —— 4.在 Combine 中使用 KVO

      本文首发于 Ficow Shen's Blog,原文地址: Combine 框架,从0到1 -- 4.在 Combine 中使用 KVO.   内容概览 前言 用 KVO 监控改动 将 KVO 代 ...

  5. swift 中关于open ,public ,fileprivate,private ,internal,修饰的说明

    关于 swift 中的open ,public ,fileprivate,private, internal的区别 以下按照修饰关键字的访问约束范围 从约束的限定范围大到小的排序进行说明 open,p ...

  6. 阿里巴巴最新开源项目 - [HandyJSON] 在Swift中优雅地处理JSON

    项目名称:HandyJSON 项目地址:https://github.com/alibaba/handyjson 背景 JSON是移动端开发常用的应用层数据交换协议.最常见的场景便是,客户端向服务端发 ...

  7. Swift中的可选链与内存管理(干货系列)

    干货之前:补充一下可选链(optional chain) class A { var p: B? } class B { var p: C? } class C { func cm() -> S ...

  8. 在Swift中实现单例方法

    在写Swift的单例方法之前可以温习一下Objective-C中单例的写法: + (instancetype)sharedSingleton{ static id instance; static d ...

  9. [翻译]理解Swift中的Optional

    原文出处:Understanding Optionals in Swift 苹果新的Swift编程语言带来了一些新的技巧,能使软件开发比以往更方便.更安全.然而,一个很有力的特性Optional,在你 ...

  10. 窥探Swift之使用Web浏览器编译Swift代码以及Swift中的泛型

    有的小伙伴会问:博主,没有Mac怎么学Swift语言呢,我想学Swift,但前提得买个Mac.非也,非也.如果你想了解或者初步学习Swift语言的话,你可以登录这个网站:http://swiftstu ...

随机推荐

  1. 【CTO变形记】有序定无序—为什么越努力,越无力

      前言:我们用自己构建的认知结构来理解和映射这个世界,通过外界的反馈来调整现有的认知.但面对的现实越来越复杂,以及面对更多的未知且陌生的情况时,我们常常试图去"修整"接受到的信息 ...

  2. 亲测有效! TG Pro 实时温度工具 V2.7.6 for mac 破解版

    亲测有效! TG Pro 实时温度工具 V2.7.6 for mac 破解版 TG Pro (Temperature Gauge Pro) 是一款专业显示你的Mac实时温度的软件,可以在系统内的菜单栏 ...

  3. 学习Java Day 5

    今天看视频学习了一下eclipse的使用方法,解决了昨天运行不了的结果,并尝试了一下java的输入:

  4. 学习Java Day24

    今天明白了 一.面向对象(面向过程) 1. 面向对象 找对象(封装了过程)来干. 例如:洗衣服(洗衣机就是对象). 2. 面向对象思想特点 是一种更符合我们思想习惯的思想. 可以将复杂的事情简单化.  ...

  5. js中的Object.keys、array.map、groupBy、call、apply总结分享

    分享几个js中的函数 Object.keys() 首先这个函数是用来干嘛的呢?是用来把一个json字符串里的key全都取出来重新整成一个数组的方法,那么这个函数怎么用呢,接下来贴出我最近碰见的用法: ...

  6. 推荐一款.Net Core开发的后台管理系统YiShaAdmin

    若依(RuoYi)是码云上一款精美的开源快速开发平台,作者毫无保留给个人及企业免费使用.RuoYi目前有三个版本:普通版本(RuoYi).前后端分离版本(RuoYi-Vue).微服务版本(RuoYi- ...

  7. 利用CRT配合VBS脚本实现自动化巡检

    利用CRT配合VBS脚本实现自动化巡检 以山石防火墙巡检为例 目录 利用CRT配合VBS脚本实现自动化巡检 1 设备列表文件:list.txt 2 VBS脚本: 2022山石巡检.vbs 3 使用方式 ...

  8. Python连接hadoop-hive连接方法

    import impala.dbapi as ipdbconn = ipdb.connect(host='IP', port= 端口, database='数据库名', auth_mechanism= ...

  9. 基于C++的OpenGL 03 之纹理

    1. 概述 本文基于C++语言,描述OpenGL的纹理 前置知识可参考: 基于C++的OpenGL 02 之着色器 - 当时明月在曾照彩云归 - 博客园 (cnblogs.com) 笔者这里不过多描述 ...

  10. kingbase字符类数据类型和oracle字符类型的区别

    为兼容Oracle的数据类型,KingbaseES扩展了Oracle的NUMBER.VARCHAR2.CHAR(n)和DATE类型.该措施使得移植Oracle的Create Table等DDL语句时, ...