为 UITableView 启用分页后 table 重新加载后 UITableViewCell 的奇怪行为

Weird behaviour of UITableViewCell after table reload when paging enabled for UITableView

我有一个 UITableView 并且在 UITableViewCell 内,我添加了视图并尝试根据屏幕高度或 UITableView 设置该视图的高度或单元格的高度s height。最初,我能够做到这一点,但是在 viewWillAppear 重新加载 table 时,无法为该视图或单元格的高度设置正确的高度。是身高问题还是其他什么问题,无法识别。任何帮助将不胜感激,感谢您的回复。问题的标题可能会令人困惑,或者您是否发现了任何不相关的代码,欢迎提出建议(编辑)。

代码:

import UIKit

class PageViewController: UIViewController {
    @IBOutlet weak var tblPager: UITableView!
    let screenHeight = UIScreen.main.bounds.size.height
    
    let vColors: [UIColor] = [.red, .blue, .orange, .brown, .cyan, .darkGray, .green, .red, .blue, .orange, .brown, .cyan, .darkGray, .green]

    var pageSizeHeight: CGFloat = 0

    override func viewDidLoad() {
        super.viewDidLoad()

        pageSizeHeight = screenHeight - (getTopSafeArea() + getBottomSafeArea() + 54)
    }
   
    override func viewWillAppear(_ animated: Bool) {
        
        super.viewWillAppear(animated)
        
        delay(interval: 10.0) {
            
            print("Reload table after 10 seconds")
            self.tblPager.reloadData()
        }
    }
    
}

//MARK:- TableView Delegate
extension PageViewController: UITableViewDelegate, UITableViewDataSource {
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return vColors.count
    }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "PageCell", for: indexPath) as! PageCell
        cell.backgroundColor = vColors[indexPath.row]
        
        cell.viewHeight.constant = pageSizeHeight
        return cell
    }
    
}

class PageCell: UITableViewCell {
    @IBOutlet weak var vwPage: UIView!
    @IBOutlet weak var viewHeight: NSLayoutConstraint!
}

func getTopSafeArea() -> CGFloat {
    let window = UIApplication.shared.keyWindow
    let topPadding = window?.safeAreaInsets.top ?? 0
    return topPadding
}

func getBottomSafeArea() -> CGFloat {
    let window = UIApplication.shared.keyWindow
    let bottomPadding = window?.safeAreaInsets.bottom ?? 0
    return bottomPadding
}

func delay(interval: TimeInterval, closure: @escaping () -> Void) {
    DispatchQueue.main.asyncAfter(deadline: .now() + interval) {
        closure()
    }
}

输出:

如果所有单元格都具有相同的高度,为什么不在 viewWillLayoutSubviews 方法中设置 rowHeight 属性?

 override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()
        tblPager.rowHeight = tblPager.frame.height
    }

感谢@Desdenova 纠正我


通过在 PageViewControllerviewDidLoad 中将 tblPagerdataSourcedelegate 设置为自身并设置 rowHeight 属性 在 viewDidLayoutSubviews 中,tableView 的行为符合预期。

 override func viewDidLoad() {
        super.viewDidLoad()
        tblPager.register(UINib(nibName: "PageTableViewCell", bundle: nil), forCellReuseIdentifier: "PageCell")
        tblPager.dataSource = self
        tblPager.delegate = self
    }
    
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        tblPager.rowHeight = tblPager.frame.size.height
    }

Link 到 tableView 的高度,你的 table view 有你需要的所有尺寸。

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) {
   // ...
   cell.viewHeight.constant = tableView.frame.size.heigh
   // ...
}

或删除viewHeight约束并使用委托方法设置行高

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
   return tableView.frame.size.height
}

UPD:

TableView 使用 estimatedRowHeight 计算其滚动偏移量。如果我们启用了分页但未配置 estimatedRowHeight.

,这确实会在重新加载期间产生问题

解决方案一: 实施 estimatedHeightForRowAt 委托

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
     return tableView.frame.size.height
}

方案二: 设置 tableView.estimatedRowHeight = 0 并使用 heightForRowAt 委托而不是 viewHeight 约束