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

iOS UITableViewCell自动布局不刷新:图片显示异常求助

问题:UITableViewCell中图片初始显示为正方形,滚动后才适配正确高度

我在制作帖子列表布局,已通过独立ImageCell.xib完成图文布局设计,并在viewDidLoad()中完成Cell注册。当前内容可完整显示,但存在布局渲染问题:上传矩形图片时,列表中该图片初始显示为正方形,仅在滚动后对应的ImageCell才会适配完整高度。

相关代码片段

ImageCell类

class ImageCell: UITableViewCell {
    //MARK: - Properties
    @IBOutlet weak var lblUserName: NBLabel!
    @IBOutlet weak var imgProfile: UIImageView! {
        didSet{
          imgProfile.layer.cornerRadius = imgProfile.frame.size.height / 2
          imgProfile.clipsToBounds = true
        }
    }
    @IBOutlet weak var imgFeedBG: ScaledHeightImageView!

    static let identifier = "ImageCell"
    override func awakeFromNib() {
       super.awakeFromNib()
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        DispatchQueue.main.asyncAfter(deadline: .now()) {
        if self.imgFeedBG != nil {
             self.imgFeedBG.contentMode = .scaleAspectFill
        }
        self.setNeedsLayout()
        self.needsUpdateConstraints()
        self.setNeedsDisplay()
        self.layoutIfNeeded()
     }
   }
   override func prepareForReuse() {
       self.lblDesc.text = nil
       self.imgFeedBG.image = nil
       super.prepareForReuse()
   }
   func setupWithItem(_ dict: PostElement) {
        let feedImageUrl = dict.imageURL.replacingOccurrences(of: " ", with: "%20")
        self.imgFeedBG.sd_imageIndicator = SDWebImageActivityIndicator.whiteLarge
    }
}

PostVC类

class PostVC: UIViewController {
     
    @IBOutlet weak var tableViewPosts: UITableView!
    var arrData = [PostElement]()
    override func viewDidLoad() {
        super.viewDidLoad()
        self.tableViewPosts.estimatedSectionHeaderHeight = 0
        self.tableViewPosts.estimatedSectionFooterHeight = 0
        tableViewPosts?.register(UINib(nibName: ImageCell.identifier, bundle: nil), forCellReuseIdentifier: ImageCell.identifier)
        self.tableViewPosts.delegate = self
        self.tableViewPosts.dataSource = self
    }
    override func viewDidAppear(_ animated : Bool) {
        super.viewDidAppear(animated)
        /*
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.1, execute: {
            self.tableViewPosts.beginUpdates()
            self.tableViewPosts.setNeedsDisplay()
            self.tableViewPosts.endUpdates()
        })
        */
        UIView.performWithoutAnimation {
           self.tableViewPosts.beginUpdates()
           self.tableViewPosts.reloadData()
           self.tableViewPosts.endUpdates()
        }
   }
}

extension PostVC : UITableViewDelegate, UITableViewDataSource {
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let dict = arrData[indexPath.row]
        guard let cell = tableView.dequeueReusableCell(withIdentifier: ImageCell.identifier) as? ImageCell else {return UITableViewCell()}
        cell.setupWithItem(dict)
        DispatchQueue.main.async {
            UIView.performWithoutAnimation {
                cell.setNeedsLayout()
                cell.layoutIfNeeded()
            }
        }
        return cell
    }
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat  {
       return UITableView.automaticDimension
    }

    func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
       return 100 // UITableView.automaticDimension
    }
 }

补充说明:

  • 已参考Xib设计图确认布局约束设置
  • 当前错误效果:矩形图片初始显示为正方形,滚动Cell出屏再返回后高度恢复正常

解决方案

1. 完善ScaledHeightImageView的自适应逻辑

确保自定义图片视图能根据图片宽高比自动计算高度,并在图片加载完成后触发布局更新:

class ScaledHeightImageView: UIImageView {
    override var image: UIImage? {
        didSet {
            invalidateIntrinsicContentSize()
            superview?.setNeedsLayout()
            superview?.layoutIfNeeded()
        }
    }
    
    override var intrinsicContentSize: CGSize {
        guard let image = image else { return super.intrinsicContentSize }
        let width = bounds.width
        let height = (image.size.height / image.size.width) * width
        return CGSize(width: width, height: height)
    }
}

2. 清理ImageCell中冗余的布局代码

删除layoutSubviews里的异步操作,避免打乱布局更新时机:

override func layoutSubviews() {
    super.layoutSubviews()
    if imgFeedBG != nil {
        imgFeedBG.contentMode = .scaleAspectFill
    }
}

3. 图片加载完成后触发Cell高度更新

修改ImageCell的setupWithItem方法,利用SDWebImage的回调通知TableView更新对应Cell高度:

func setupWithItem(_ dict: PostElement) {
    let feedImageUrl = dict.imageURL.replacingOccurrences(of: " ", with: "%20")
    self.imgFeedBG.sd_imageIndicator = SDWebImageActivityIndicator.whiteLarge
    // 图片加载完成后刷新Cell高度
    self.imgFeedBG.sd_setImage(with: URL(string: feedImageUrl)) { [weak self] _, _, _, _ in
        guard let self = self,
              let tableView = self.superview as? UITableView,
              let indexPath = tableView.indexPath(for: self) else { return }
        
        tableView.performBatchUpdates({
            tableView.reloadRows(at: [indexPath], with: .none)
        }, completion: nil)
    }
}

4. 优化TableView的高度估算与刷新逻辑

  • 将estimatedHeightForRowAt设置为更接近实际的数值,或直接使用UITableView.automaticDimension
  • 删除viewDidAppear中冗余的TableView刷新代码,避免不必要的布局抖动

5. 验证Xib约束正确性

检查ImageCell.xib:

  • imgFeedBG需设置左右边距、顶部间距约束,不要设置固定高度
  • Cell的底部约束必须连接到imgFeedBG的底部,确保TableView能正确计算自动高度

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 05:15:44