Swift 5 table 带有 UIImage 的视图单元格显得非常高并且图像极度缩放

Swift 5 table view cell with UIImage appears very tall and image extremely zoomed

我正在开发一个聊天应用程序,因此行高各不相同。我将单独的单元格用于纯 txt 消息和带有图像(可能还有文本)的消息。我允许用户 select 来自 phone 的图像。我在单独的 VC 中显示该图像,如果他选择并发送文本,他可以在其中输入文本。我有一个 msg 模型,这意味着我在 base64 和图像格式之间进行转换。我试图最大程度地简化我的单元格 class 以理解以下问题:图像视图中的图像看起来超出了正常 phone 缩放所允许的范围;细胞的高度是巨大的。在我需要使用的单元格 class 上,我有更多的项目和约束,但这里感兴趣的基本逻辑如下:

    fileprivate func configureMsgsTable() {
    tableView.contentInsetAdjustmentBehavior = .automatic
    tableView.backgroundColor = .clear
    tableView.keyboardDismissMode = .interactive
    tableView.separatorStyle = .none
    tableView.showsVerticalScrollIndicator = false
    tableView.rowHeight = UITableView.automaticDimension
    tableView.estimatedRowHeight = 100
    tableView.sectionFooterHeight = 0.0
}

这些是我用于 encoding/decoding:

的函数
fileprivate func convertImageToBase64String (img: UIImage) -> String {
    let imageData:NSData = img.jpegData(compressionQuality: 0.50)! as NSData
    let imgString = imageData.base64EncodedString(options: Data.Base64EncodingOptions.lineLength64Characters)
    return imgString
}
fileprivate func convertBase64StringToImage (imageBase64String:String) -> UIImage {
    let imageData = Data.init(base64Encoded: imageBase64String, options: Data.Base64DecodingOptions.ignoreUnknownCharacters)
    let image = UIImage(data: imageData!)
    return image!
}

这是单元格 class。

class MsgWithImg: UITableViewCell {
//MARK: - Observer.
internal var valuesToDisplay: NewProjectGrpMsgModel! {
    didSet {
        imgView.image = convertBase64StringToImage(imageBase64String: valuesToDisplay.msgAttachment)
    }
}
//MARK: - Properties.
fileprivate let imgView: UIImageView = {
    let imgView = UIImageView(frame: .zero)
    imgView.clipsToBounds = true
    imgView.translatesAutoresizingMaskIntoConstraints = false
    imgView.contentMode = .scaleAspectFill
    imgView.layer.cornerRadius = 0
    return imgView
}()
//MARK: - Init.
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    backgroundColor = .clear
    clipsToBounds = true
    selectionStyle = .none
    setupViews()
}
required init?(coder: NSCoder) {fatalError("init(coder:) has not been implemented")}
fileprivate func setupViews() {
    contentView.addSubview(imgView)
    let imgViewConstraints = [
        imgView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 3),
        imgView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -3),
        imgView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
        imgView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -45)
    ]
    NSLayoutConstraint.activate(imgViewConstraints)
}

} 我花了一些时间认为这是一个自动布局问题;或者 table 行高是自动的。这就是为什么我只使用图像视图构建此测试单元 class 的原因。但我认为这个问题具有不同的性质。我确实阅读了很多关于我在这个网站上能找到的相关内容的答案,但我无法确定问题出在哪里,控制台也没有打印出任何内容。

问题是,如果您不给 UIImageView 宽度和高度,它的 intrinsicContentSize 就会变成分配给它的图像的大小。

按原样使用您的代码,您通过约束其前导和尾随锚点为图像视图提供了 宽度,但您没有为它提供 height -- 本身或单元格的高度(因为你想要自动调整单元格大小)。

所以,如果我们使用这四张图片:

生成的 table 视图如下所示:

这是 iPhone 13 上发生的事情(注意:所有尺寸都是四舍五入的)...

对于 100x200 图片:

  • 您的 Leading/Trailing 约束使图像视图框架宽 345 磅
  • 未设置高度,因此自动布局使用图像大小(200 磅),将图像视图框架设置为 200 磅高
  • 图像视图设置为.scaleAspectFill,因此缩放后的尺寸为345 x 690

对于 100x300 图片:

  • 您的 Leading/Trailing 约束使图像视图框架宽 345 磅
  • 未设置高度,因此自动布局使用图像大小(300 磅),将图像视图框架设置为 300 磅高
  • 图像视图设置为.scaleAspectFill,因此缩放后的尺寸为345 x 1035

对于 600x200 图片:

  • 您的 Leading/Trailing 约束使图像视图框架宽 345 磅
  • 未设置高度,因此自动布局使用图像大小(200 磅),将图像视图框架设置为 200 磅高
  • 图像视图设置为.scaleAspectFill,因此缩放后的尺寸为600 x 200

对于 800x600 图片:

  • 您的 Leading/Trailing 约束使图像视图框架宽 345 磅
  • 未设置高度,因此自动布局使用图像大小(600 磅),将图像视图框架设置为 600 磅高
  • 图像视图设置为.scaleAspectFill,因此缩放后的尺寸为800 x 600

如果我们将图像视图设置为 .scaleAspectFit(红色背景以便我们可以看到框架),可能会更清楚:

作为一般规则,通常给图像视图一个固定大小(或比例大小),并使用 .scaleAspectFit 来显示完整的图像。或者,也很常见,使用预处理器为 table 视图单元格生成“缩略图”大小的图像。