Swift - 异步编程库PromiseKit使用详解4(KVO的扩展)
作者:hangge | 2018-12-10 08:10
KVO(键值观察)是一种 Objective-C 的回调机制,全称为:key-value-observing。该机制简单来说就是在某个对象注册监听者后,当被监听的对象发生改变时,对象会发送一个通知给监听者,以便监听者执行回调操作。
同样地,PromiseKit 也对 KVO 提供了相关的扩展,方便我们使用。
五、KVO 的扩展
1,准备工作
我们同样要安装 PromiseKit 库,以及相关的 PMKFoundation 扩展库,具体步骤参考我之前的文章:
2,监听基本类型的属性
(1)我们创建一个定时器,每隔 1 秒钟给变量 message 尾部添加一个感叹号(!)。同时对这个属性进行监听,当值改变时将最新值输出到控制台中。
注意:监听的属性需要有 dynamic 修饰符。
import UIKit import PromiseKit import PMKFoundation class ViewController: UIViewController { @objc dynamic var message = "hangge.com" override func viewDidLoad() { super.viewDidLoad() //定时器(1秒执行一次) Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ViewController.changeMessage), userInfo: nil, repeats: true) //观察message参数变化 observeMessage() } //计时器时间一到修改参数内容 @objc func changeMessage(){ //每次给字符串尾部添加一个感叹号 self.message.append("!") } //观察message参数变化 func observeMessage(){ self.observe(.promise, keyPath: #keyPath(ViewController.message)).done { value in print(value ?? "") //继续观察 self.observeMessage() } } }
(2)运行结果如下:
3,监听视图尺寸变化
(1)我们对 view.frame 进行监听,当其改变时将最新值输出到控制台中。
import UIKit import PromiseKit import PMKFoundation class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() //监听view.frame变化 observeViewFrame() } //监听view.frame变化 func observeViewFrame(){ self.observe(.promise, keyPath: #keyPath(view.frame)).done { frame in print("--- 视图尺寸发生变化 ---") print(frame!) //继续观察 self.observeViewFrame() } } }
(2)程序启动后默认是竖屏状态,接着我们将其变成横屏显示。控制台输出内容如下:
4,渐变导航栏效果
(1)效果图如下,导航栏会随着 tableView 的滑动而发生不同的变化:
- 默认情况下,导航栏背景是完全透明的。
- 当 tableView 向上滑动时,导航栏背景逐渐显示出来。
- 当 tableView 下载滑动时,导航栏背景又逐渐消失。
(2)我们可以通过 KVO 监听偏移量的变化来动态改变导航栏的背景透明度:
import UIKit import PromiseKit import PMKFoundation class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { @objc var tableView:UITableView! //导航栏背景视图 var barImageView:UIView? 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.delegate = self self.tableView.dataSource = self //创建一个重用的单元格 self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "SwiftCell") self.view.addSubview(self.tableView) //使用kvo来监听视图偏移量变化 observeTableViewContentOffset() } //监听tableView.contentOffset变化 func observeTableViewContentOffset(){ self.observe(.promise, keyPath: #keyPath(tableView.contentOffset)).done { oldOffset in var delta = self.tableView.contentOffset.y / CGFloat(64) + 1 delta = CGFloat.maximum(delta, 0) self.barImageView?.alpha = CGFloat.minimum(delta, 1) //继续观察 self.observeTableViewContentOffset() } } //在本例中,只有一个分区 func numberOfSections(in tableView: UITableView) -> Int { return 1 } //返回表格行数 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 50 } //创建各单元显示内容(创建参数indexPath指定的单元) func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { //为了提供表格显示性能,已创建完成的单元需重复使用 let identify = "SwiftCell" //同一形式的单元格重复使用,在声明时已注册 let cell = tableView.dequeueReusableCell(withIdentifier: identify, for: indexPath) cell.accessoryType = .disclosureIndicator cell.textLabel?.text = "这个是条目\(indexPath.row)" return cell } }
全部评论(0)