You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 20:06:01