Swift中点击按钮时如何隐藏UITableView并将其高度置为0
问题原因
isHidden属性仅控制视图可见性,不会修改视图的布局约束占用的空间,你隐藏tableView后没有主动修改高度约束,之前设置的contentSize对应的高度值仍会生效,所以会留空白- 你每次点击按钮都重复添加KVO观察者,不仅会导致多次回调,还会在你隐藏tableView时,
reloadData触发contentSize更新,主动把高度又改成了内容高度,抵消了你预期的隐藏效果 - 隐藏tableView的分支没有主动把高度约束设为0,也没有做过滤逻辑
修复方案
修正后完整代码如下:
class WorkVC: UIViewController, UITableViewDelegate, UITableViewDataSource { @IBOutlet weak var workExpTablHeight: NSLayoutConstraint! @IBOutlet weak var workExpTableview: UITableView! override func viewDidLoad() { super.viewDidLoad() workExpTablHeight.constant = 0 workExpTableview.isHidden = true // KVO只在初始化时添加一次即可,不要每次点击都重复添加 workExpTableview.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil) } @IBAction func workExpBtn(_ sender: Any) { let willBeHidden = !workExpTableview.isHidden workExpTableview.isHidden = willBeHidden if willBeHidden { // 隐藏时直接把高度设为0,立刻刷新布局 workExpTablHeight.constant = 0 view.layoutIfNeeded() } else { // 显示时才刷新列表,触发KVO自动更新为内容高度 workExpTableview.reloadData() } } override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { // 增加隐藏状态的过滤,隐藏时不更新高度 guard tableview == self.workExpTableview, keyPath == "contentSize", !workExpTableview.isHidden else { return } if let newSize = change?[.newKey] as? CGSize { workExpTablHeight.constant = newSize.height view.layoutIfNeeded() } } // 页面销毁时移除KVO,避免崩溃和内存泄漏 deinit { workExpTableview.removeObserver(self, forKeyPath: "contentSize") } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 10 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "WorkExpCell", for: indexPath) as! WorkExpCell cell.selectionStyle = .none return cell } }
额外优化建议
- 如果项目最低支持iOS 11及以上,可以不用KVO实现自适应高度,reloadData后直接调用
workExpTableview.sizeToFit()读取高度即可,逻辑更简洁 - 也可以搭配UIStackView作为容器,隐藏时自动收缩空间,不需要手动管理高度约束
内容的提问来源于stack exchange,提问作者User123
相关产品推荐
相关产品推荐

