在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
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 的地方都可以使用 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)
原文地址:https://www.cnblogs.com/zbblog/p/15906682.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。