KVO的使用,实用案例:导航栏背景颜色渐变

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.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)
            })
    }
}

参考文章:Swift - RxSwift的使用详解64(键值观察KVO的使用)

你可能感兴趣的:(KVO的使用,实用案例:导航栏背景颜色渐变)