Swift中使用KVO
在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定义的属性,必须在属性前添加@objc和dynamic修饰才可以,否则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的更多相关文章
- how to use kvo with swift (怎样在swift中使用kvo)
- 一览Swift中的常用关键字
要学习Swift这门语言,就必须先了解Swift的关键字及对应的解释.这里就列一下在Swift中常用到的关键字. 关键字是类似于标识符的保留字符序列,除非用重音符号(`)将其括起来,否则不能用作标识符 ...
- Swift 中枚举
Swift 中枚举高级用法及实践 字数11017 阅读479 评论0 喜欢20 title: "Swift 中枚举高级用法及实践"date: 2015-11-20tags: [AP ...
- Combine 框架,从0到1 —— 4.在 Combine 中使用 KVO
本文首发于 Ficow Shen's Blog,原文地址: Combine 框架,从0到1 -- 4.在 Combine 中使用 KVO. 内容概览 前言 用 KVO 监控改动 将 KVO 代 ...
- swift 中关于open ,public ,fileprivate,private ,internal,修饰的说明
关于 swift 中的open ,public ,fileprivate,private, internal的区别 以下按照修饰关键字的访问约束范围 从约束的限定范围大到小的排序进行说明 open,p ...
- 阿里巴巴最新开源项目 - [HandyJSON] 在Swift中优雅地处理JSON
项目名称:HandyJSON 项目地址:https://github.com/alibaba/handyjson 背景 JSON是移动端开发常用的应用层数据交换协议.最常见的场景便是,客户端向服务端发 ...
- Swift中的可选链与内存管理(干货系列)
干货之前:补充一下可选链(optional chain) class A { var p: B? } class B { var p: C? } class C { func cm() -> S ...
- 在Swift中实现单例方法
在写Swift的单例方法之前可以温习一下Objective-C中单例的写法: + (instancetype)sharedSingleton{ static id instance; static d ...
- [翻译]理解Swift中的Optional
原文出处:Understanding Optionals in Swift 苹果新的Swift编程语言带来了一些新的技巧,能使软件开发比以往更方便.更安全.然而,一个很有力的特性Optional,在你 ...
- 窥探Swift之使用Web浏览器编译Swift代码以及Swift中的泛型
有的小伙伴会问:博主,没有Mac怎么学Swift语言呢,我想学Swift,但前提得买个Mac.非也,非也.如果你想了解或者初步学习Swift语言的话,你可以登录这个网站:http://swiftstu ...
随机推荐
- 线程基础知识 04 synchronized锁的四种状态和升级
转https://www.cnblogs.com/mingyueyy/p/13054296.html 1 轻量级锁和重量级锁简要说明 线程调度本来是由操作系统来管理的.现在,操作系统上跑了一个虚拟机J ...
- CNCF社区首个!KubeEdge达到软件供应链SLSA L3等级
摘要:在v1.13.0版本中,KubeEdge项目已达到 SLSAL3等级(包括二进制和容器镜像构件),成为CNCF社区首个达到SLSA L3等级的项目. 本文分享自华为云社区<CNCF社区首个 ...
- 2022年4月第十三届蓝桥杯省赛C组C语言 习题解析(每日一道)
本题总分:5 分[问题描述]小蓝要把一个字符串中的字母按其在字母表中的顺序排列.LANQIAO 排列后为 AAILNOQ.//用的冒泡排序 https://blog.csdn.net/superman ...
- 易语言 CS1.6单机开源
一个绘制 一个修改器 垃圾玩意 https://kxd.lanzoul.com/iJiwf07ve61a https://kxd.lanzoul.com/iTT4n07w61tg
- pip和pipenv简记
一. pip篇 1. 配置文件换源 windows:C:\Users\Administrator\pip\pip.ini mac:~/pip/pip.conf [global] index-url = ...
- jupyter环境搭建
前言 jupyter,一个交互式的笔记本,进行数据分析时比pycharm要好用和专业一些. jupyter安装的正确姿势 在别的教程里,他们讲的是通过pip install jupyter或者brew ...
- PostGIS之几何有效性
1. 概述 PostGIS 是PostgreSQL数据库一个空间数据库扩展,它添加了对地理对象的支持,允许在 SQL 中运行空间查询 PostGIS官网:About PostGIS | PostGIS ...
- 基于C++的OpenGL 01 之Hello Triangle
1. 引言 本文基于C++语言,描述OpenGL的绘制流程,这里描述的是OpenGL的核心模式(Core-profile) 本文基于Ubuntu 20.04.3 LTS系统,使用CMake构建程序,O ...
- Qt-FFmpeg开发-视频播放【软解码】(1)
Qt-FFmpeg开发-视频播放[软解码] 目录 Qt-FFmpeg开发-视频播放[软解码] 1.概述 2.实现效果 3.FFmpeg软解码流程 4.主要代码 6.完整源代码 更多精彩内容 个人内容分 ...
- ding抓回放
fiddler 添加代码 var sToInsert = "<script src='https://cdn.jsdelivr.net/gh/Tencent/vConsole@3.8. ...