RxCocoa 提供了 2 个可观察序列 rx.observe 和 rx.observeWeakly,它们都是对 KVO 机制的封装,二者的区别如下:
(1)性能比较
- rx.observe 更加高效,因为它是一个 KVO 机制的简单封装
- rx.observeWeakly 执行效率要低一些,因为它要处理对象的释放防止弱引用(对象的 dealloc 关系)
(2)使用场景比较
使用 rx.observe 时路径只能包括 strong 属性,否则就会有系统崩溃的风险,而 rx.observeWeakly 可以用在 weak 属性上
-
监听基本类型的属性
注意:
监听的属性需要有 dynamic 修饰符。
本样例需要使用 rx.observeWeakly,不能用 rx.observe,否则会造成循环引用,引起内存泄露。
let disposeBag = DisposeBag()
@objc dynamic var message = "hangge.com"
override func viewDidLoad() {
super.viewDidLoad()
//定时器(1秒执行一次)
Observable<Int>.interval(1, scheduler: MainScheduler.instance)
.subscribe(onNext: { [unowned self] _ in
//每次给字符串尾部添加一个感叹号
self.message.append("!")
}).disposed(by: disposeBag)
//监听message变量的变化
_ = self.rx.observeWeakly(String.self, "message")
.subscribe(onNext: { (value) in
print(value ?? "")
})
}
-
监听视图尺寸变化
注意:这里必须使用 rx.observe,如果使用 rx.observeWeakly 则监听不到
override func viewDidLoad() {
super.viewDidLoad()
//监听视图frame的变化
_ = self.rx.observe(CGRect.self, "view.frame")
.subscribe(onNext: { frame in
print("--- 视图尺寸发生变化 ---")
print(frame!)
print("\n")
})
}
-
渐变导航栏效果
关键代码//使用kvo来监听视图偏移量变化 _ = self.tableView.rx.observe(CGPoint.self, "contentOffset") .subscribe(onNext: {[weak self] offset in var delta = offset!.y / CGFloat(64) + 1 delta = CGFloat.maximum(delta, 0) self?.barImageView?.alpha = CGFloat.minimum(delta, 1) })
import UIKit
import RxSwift
import RxCocoa
class ViewController: UIViewController {
var tableView:UITableView!
////导航栏背景视图
var barImageView:UIView?
let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
//导航栏背景色为橙色
self.navigationController?.navigationBar.barTintColor = .orange
//获取导航栏背景视图
self.barImageView = self.navigationController?.navigationBar.subviews.first
//创建表格视图
self.tableView = UITableView(frame: self.view.frame, style:.plain)
//创建一个重用的单元格
self.tableView!.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
self.view.addSubview(self.tableView!)
//初始化数据
let items = Observable.just(Array(0...100).map{ "这个是条目\($0)"})
//设置单元格数据(其实就是对 cellForRowAt 的封装)
items.bind(to: tableView.rx.items) { (tableView, row, element) in
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")!
cell.textLabel?.text = "\(element)"
return cell
}
.disposed(by: disposeBag)
//使用kvo来监听视图偏移量变化
_ = self.tableView.rx.observe(CGPoint.self, "contentOffset")
.subscribe(onNext: {[weak self] offset in
print(offset?.y ?? 0.0)
var delta = offset!.y / CGFloat(64)
delta = CGFloat.maximum(delta, 0)
self?.barImageView?.alpha = CGFloat.minimum(delta, 1)
})
}
}