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

Swift4实现ScrollView中适配动态高度的多个TableView

当然可以实现!这种独立TableView的方案反而比合并到单个TableView更清晰,维护起来也更省心,完全适配你iOS 11.3 + Swift 4 + Xcode 9.3的技术栈。下面是具体的实现思路和代码示例:

核心思路

我们会用「UIScrollView + 垂直UIStackView」作为容器,把4个独立的UITableView放进StackView里。关键是让每个TableView禁用自身滚动,并根据内容动态调整高度,最后由外层ScrollView负责整体滚动。

步骤1:布局容器设置

首先在Storyboard或代码里搭建基础布局:

  • 给ViewController添加一个UIScrollView,让它的leading/trailing/top/bottom和父视图完全对齐。
  • 在ScrollView内部添加一个垂直排列的UIStackView,设置它的leading/trailing/top/bottom和ScrollView的contentLayoutGuide对齐,同时让StackView的width和ScrollView的frameLayoutGuide对齐(保证TableView宽度和屏幕一致)。

步骤2:配置每个独立的TableView

每个TableView都需要做以下配置,才能实现动态高度:

  • 禁用自身滚动:tableView.isScrollEnabled = false(把滚动权交给外层ScrollView)
  • 开启自动行高:tableView.rowHeight = UITableView.automaticDimension,同时设置estimatedRowHeight(比如44,给系统一个初始参考值)
  • 给每个TableView添加高度约束,后续动态更新这个约束的constant值来匹配内容高度

代码示例:初始化TableView

import UIKit

class MultiTableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    
    @IBOutlet weak var scrollView: UIScrollView!
    @IBOutlet weak var verticalStackView: UIStackView!
    
    // 四个独立的TableView
    private var tableView1: UITableView!
    private var tableView2: UITableView!
    private var tableView3: UITableView!
    private var tableView4: UITableView!
    
    // 对应每个TableView的高度约束
    private var tv1HeightConstraint: NSLayoutConstraint!
    private var tv2HeightConstraint: NSLayoutConstraint!
    private var tv3HeightConstraint: NSLayoutConstraint!
    private var tv4HeightConstraint: NSLayoutConstraint!
    
    // 模拟四个动态数据源
    private var dataSource1: [String] = []
    private var dataSource2: [String] = []
    private var dataSource3: [String] = []
    private var dataSource4: [String] = []

    override func viewDidLoad() {
        super.viewDidLoad()
        setupAllTableViews()
        loadDynamicData()
    }
    
    private func setupAllTableViews() {
        // 复用方法初始化每个TableView
        setupSingleTableView(&tableView1, heightConstraint: &tv1HeightConstraint)
        setupSingleTableView(&tableView2, heightConstraint: &tv2HeightConstraint)
        setupSingleTableView(&tableView3, heightConstraint: &tv3HeightConstraint)
        setupSingleTableView(&tableView4, heightConstraint: &tv4HeightConstraint)
        
        // 将TableView添加到StackView
        [tableView1, tableView2, tableView3, tableView4].forEach {
            verticalStackView.addArrangedSubview($0)
        }
    }
    
    private func setupSingleTableView(_ tableView: inout UITableView?, heightConstraint: inout NSLayoutConstraint?) {
        tableView = UITableView(frame: .zero, style: .plain)
        tableView?.translatesAutoresizingMaskIntoConstraints = false
        tableView?.isScrollEnabled = false
        tableView?.rowHeight = UITableView.automaticDimension
        tableView?.estimatedRowHeight = 44
        tableView?.delegate = self
        tableView?.dataSource = self
        // 注册自定义Cell(这里替换成你自己的Cell类和标识符)
        tableView?.register(UITableViewCell.self, forCellReuseIdentifier: "DefaultCell")
        
        // 添加高度约束
        heightConstraint = tableView?.heightAnchor.constraint(equalToConstant: 0)
        heightConstraint?.isActive = true
    }
}

步骤3:动态更新TableView高度

当数据源变化时,我们需要刷新TableView并更新它的高度约束,让StackView和外层ScrollView自动适配新的内容:

代码示例:更新数据与高度

extension MultiTableViewController {
    // 模拟加载动态数据
    private func loadDynamicData() {
        // 这里替换成你实际的数据源获取逻辑,比如网络请求后更新数组
        dataSource1 = Array(repeating: "TableView1 行数据", count: Int.random(in: 4...10))
        dataSource2 = Array(repeating: "TableView2 行数据", count: Int.random(in: 2...8))
        dataSource3 = Array(repeating: "TableView3 行数据", count: Int.random(in: 5...12))
        dataSource4 = Array(repeating: "TableView4 行数据", count: Int.random(in: 3...9))
        
        // 更新所有TableView的高度
        updateAllTableViewHeights()
    }
    
    private func updateAllTableViewHeights() {
        // 先刷新所有TableView
        tableView1.reloadData()
        tableView2.reloadData()
        tableView3.reloadData()
        tableView4.reloadData()
        
        // 强制布局,确保contentSize正确计算
        view.layoutIfNeeded()
        
        // 更新每个TableView的高度约束
        tv1HeightConstraint.constant = tableView1.contentSize.height
        tv2HeightConstraint.constant = tableView2.contentSize.height
        tv3HeightConstraint.constant = tableView3.contentSize.height
        tv4HeightConstraint.constant = tableView4.contentSize.height
        
        // 再次布局,让ScrollView更新内容尺寸
        view.layoutIfNeeded()
    }
    
    // MARK: - UITableView DataSource & Delegate
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        switch tableView {
        case tableView1: return dataSource1.count
        case tableView2: return dataSource2.count
        case tableView3: return dataSource3.count
        case tableView4: return dataSource4.count
        default: return 0
        }
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "DefaultCell", for: indexPath)
        switch tableView {
        case tableView1: cell.textLabel?.text = dataSource1[indexPath.row]
        case tableView2: cell.textLabel?.text = dataSource2[indexPath.row]
        case tableView3: cell.textLabel?.text = dataSource3[indexPath.row]
        case tableView4: cell.textLabel?.text = dataSource4[indexPath.row]
        default: break
        }
        return cell
    }
}

额外优化建议

  • 分离代理逻辑:如果四个TableView的业务逻辑差异较大,建议给每个TableView单独设置代理对象(比如创建四个小的ViewModel或Delegate类),避免在同一个ViewController里写大量switch判断,代码更易维护。
  • 监听ContentSize变化:如果担心数据更新后contentSize没有及时更新,可以用KVO监听每个TableView的contentSize属性,自动触发高度更新(代码里可以添加KVO监听逻辑,在observeValue方法里更新对应约束)。
  • Cell约束完整性:如果你的Cell是动态高度(比如包含多行文本),一定要确保Cell内部的约束是完整的(顶部、底部、左右都有明确约束),这样UITableView.automaticDimension才能正确计算行高。

内容的提问来源于stack exchange,提问作者gabicuesta

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:20:53