【问题标题】:Weird behaviour of UITableViewCell after table reload when paging enabled for UITableView为 UITableView 启用分页后重新加载表后 UITableViewCell 的奇怪行为
【发布时间】:2021-10-07 18:16:15
【问题描述】:

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

代码:

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()
    }
}

输出:

【问题讨论】:

  • 显示heightForRowAt indexPath tableView 的委托方法。
  • @Starsky 我不认为它会影响输出,所以你能详细说明一下吗?
  • 您是否尝试从cellForRowAt 设置单元格的高度?
  • @Starsky 请检查一次代码
  • 由于单元格内的视图是唯一的视图,您可以将其设置为 contentView 的大小,然后在指定的委托方法heightForRowAt 中操作单元格的高度。您在这里尝试做的事情是不正确的。如果您是 iOS 开发的新手,那么也许可以阅读一些答案 here。祝你好运!

标签: ios swift uitableview


【解决方案1】:

将它链接到 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,这确实会在重新加载期间产生问题。

解决方案 1: 实现estimatedHeightForRowAt委托

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

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

【讨论】:

  • 感谢您的回复,但您的解决方案不起作用。您能否提出其他解决方案?
  • 这应该行得通,我无法想象它不起作用的情况。我已经为这两种情况设置了sample project
  • 感谢您的回复。感谢您的努力,但是您是否在override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) delay(interval: 8.0) { print("Reload table1 after 8 seconds") self.tableView.reloadData() } } 中重新加载了override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) delay(interval: 8.0) { print("Reload table1 after 8 seconds") self.tableView.reloadData() } } 中的表格视图,并在我的代码中使用delay 函数并再次检查您的代码输出?并确保为 tableview 启用分页
  • 没有区别。它会起作用的,你可以自己尝试一下
  • 好的,我明白了...你应该设置tableView.estimatedRowHeight = pageSize。但我建议使用func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) + tableView.estimatedRowHeight = 0
【解决方案2】:

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

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

感谢@Desdenova 纠正我


通过在PageViewControllerviewDidLoad 中将tblPagerdataSourcedelegate 设置为self,并在viewDidLayoutSubviews 中设置rowHeight 属性,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
    }

【讨论】:

  • 这行不通。表在加载时不知道它的高度。试试viewWillLayoutSubviews()
  • @Desdenova 你是对的,但它也没有提供所需的输出。您也可以检查代码
  • 这不是你的错。问题很混乱,有太多不相关的代码。
  • 感谢您的回复,但您的解决方案不起作用。您能否提出其他解决方案?
  • 对不起,我能想到的就这么多。你能分享你的代码,让我试着找出错误在哪里吗? @KishanBhatiya
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-30
相关资源
最近更新 更多