iOS Swift 5中addObserver与observeValue如何实现tableView高度自适应?
基于KVO实现UITableView动态适配内容高度原理解析
你实现的功能核心依赖苹果的**KVO(键值观察)**机制,这是Foundation框架内置的属性变更通知能力,允许一个对象监听另一个对象指定属性的变化,属性值发生变更时系统会自动触发观察者的回调方法。下面结合你的代码逐段解释:
1. viewDidLoad 中的注册监听逻辑
override func viewDidLoad() { super.viewDidLoad() self.tableView.addObserver(self, forKeyPath: "contentSize", options: NSKeyValueObservingOptions.new, context: nil) }
这段代码的作用是把当前ViewController注册为tableView的观察者,具体参数含义:
- 监听的属性
contentSize是UIScrollView的固有属性(UITableView继承自UIScrollView),代表tableView所有cell、组头、组尾的总内容尺寸,只要你调用reloadData、插入删除cell、动态修改cell高度,这个属性值都会自动更新 options: .new表示属性变更时,回调方法会返回变更后的最新属性值- 传入nil的context参数是KVO用于区分不同监听的标识,你这里只有一个监听,所以可以传nil
2. observeValue 回调逻辑
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { tableView.layer.removeAllAnimations() heightTable.constant = tableView.contentSize.height UIView.animate(withDuration: 0.5) { self.updateViewConstraints() } }
这个方法是KVO的系统默认回调,只要你监听的contentSize发生变化,系统就会自动调用这个方法:
tableView.layer.removeAllAnimations():移除tableView当前所有layer层动画,避免contentSize更新时自带的滚动动画和后续的高度更新动画冲突,出现UI跳闪heightTable.constant = tableView.contentSize.height:heightTable是你给tableView添加的高度约束,直接把约束的常量值设置为内容总高度,保证tableView的展示高度刚好等于所有内容的总高度,既不会出现滚动条,也不会留空白区域- 包裹在
UIView.animate中的updateViewConstraints():将约束更新操作放在动画块中执行,让tableView的高度变化以0.5秒的平缓动画过渡,不会出现生硬的突变
注意事项
你当前的代码缺少KVO的移除逻辑,如果页面销毁时没有移除观察者,会触发野指针崩溃,建议补充以下代码:
deinit { tableView.removeObserver(self, forKeyPath: "contentSize") }
内容的提问来源于stack exchange,提问作者aditya vaghela
相关产品推荐
相关产品推荐

