Ios UICollectionViewCell:自动布局-尺寸计算不正确(偏移10磅)

Ios UICollectionViewCell:自动布局-尺寸计算不正确(偏移10磅),ios,autolayout,uikit,uicollectionviewcell,sizing,Ios,Autolayout,Uikit,Uicollectionviewcell,Sizing,我有一组具有不同布局的UICollectionViewCell子类(使用AutoLayout) 由于“自调整单元格大小”功能完全被破坏,我在数据源中手动计算大小。但是,我注意到,无论是哪种单元,计算的大小都比它应该的小10 pt 以下是我用来计算尺寸的代码: let sizeCache = CellCache() // Size cache stores previously calculated values func collectionView(_ collectionView:

我有一组具有不同布局的UICollectionViewCell子类(使用AutoLayout)

由于“自调整单元格大小”功能完全被破坏,我在数据源中手动计算大小。但是,我注意到,无论是哪种单元,计算的大小都比它应该的小10 pt

以下是我用来计算尺寸的代码:

  let sizeCache = CellCache() // Size cache stores previously calculated values
  func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    if let cachedSize = sizeCache.sizeAtIndexPath(indexPath: indexPath) {
      return cachedSize // Return cached value if it exists
    }

    // Calculate the size if not found in the cache
    let cellClass = cellTypeAt(indexPath: indexPath) // Get the class type
    let cell = sizeCache.createCellOfTypeIfNeeded(cellType: cellClass) // Dequeue or instantiate a cell
    self.collectionView(collectionView, cell: cell, configureAt: indexPath) // Ask DataSource to configure this cell
    let fittingSize = CGSize(width: collectionView.bounds.width - 16, height: 0) // Set the padding to 16
    cell.bounds = CGRect(origin: .zero, size: fittingSize) // Set cell's width
    var result = cell.contentView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize) // Calculate cell's size using AutoLayout
    result.width = collectionView.bounds.width - 16 // Set the padding
    result.height = result.height + 10 // !!! Error - Add 10 pt to the result !!!
    sizeCache.setSize(size: result, at: indexPath) // Cache the result
    return result
  }
注意末尾的那行,我必须加上10磅才能使它工作

“我的所有单元格”都是该基类的子类,该基类设置了
width
约束:

import UIKit
import SnapKit

class AutoSizingCellBase: UICollectionViewCell {
  override class var requiresConstraintBasedLayout: Bool {
    return true
  }

  private final var widthConstraint: Constraint?

  override func updateConstraints() {
    if widthConstraint == nil {
      if let window = window {
        let width = window.bounds.width - 16
        contentView.snp.makeConstraints { (make) in
          widthConstraint = make.width.equalTo(width).constraint
        }
      }
    }
    super.updateConstraints()
  }
}
该问题的例子如下:

正确的尺寸(添加10磅后)

尺寸不正确(未添加10磅)

该问题影响所有单元格。它的根本原因可能是什么

更新:约束示例 以下是我用于配置所示视图的约束条件:

  private func setupConstraints() {
    price.setContentCompressionResistancePriority(.required, for: .horizontal)
    disclosureIndicator.setContentCompressionResistancePriority(.required, for: .horizontal)
    disclosureIndicator.setContentCompressionResistancePriority(.required, for: .vertical)
    disclosureIndicator.setContentHuggingPriority(.required, for: .horizontal)
    disclosureIndicator.setContentHuggingPriority(.required, for: .vertical)

    title.snp.makeConstraints { (make) in
      make.leading.top.equalTo(contentView.layoutMarginsGuide)
      make.trailing.lessThanOrEqualTo(price.snp.leading).offset(-8)
    }

    subtitle.snp.makeConstraints { (make) in
      make.top.equalTo(title.snp.bottom).offset(8)
      make.leading.bottom.equalTo(contentView.layoutMarginsGuide)
    }

    disclosureIndicator.snp.makeConstraints { (make) in
      make.trailing.equalTo(contentView.layoutMarginsGuide)
      make.centerY.equalToSuperview()
    }

    price.snp.makeConstraints { (make) in
      make.trailing.equalTo(disclosureIndicator.snp.leading).offset(-8)
      make.centerY.equalToSuperview()
    }
  }
这是一个相当复杂的例子,但即使使用更简单的例子,问题也是可以重现的:

  private func setupConstraints() {
    button.snp.makeConstraints { (make) in
      make.width.equalToSuperview() // Button is a subview of the UIStackView
    }

    stack.snp.makeConstraints { (make) in
      make.edges.equalTo(contentView.layoutMarginsGuide)
      make.height.greaterThanOrEqualTo(150)
    }
  }
更新

在约束中添加偏移量可以解决此问题,而视图层次调试器仍显示“不明确布局”:

问题是,
10
从何而来仍然是开放的

更新3 似乎问题的一部分在于调整
布局边距

UIView.appearance().layoutMargins = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)
在我从
AppDelegate
中删除上面的行之后,大小计算变得正确,尽管单元格的外观发生了变化。 因此,我认为问题在于,出于某种原因,为调整大小而创建的单元格与从
UICollectionView
出列的单元格具有不同的插入


LayoutMargins
在添加到superview和不在视图层次结构中时,对
UICollectionViewCell
的计算方式不同

因为这条线:

UIView.appearance().layoutMargins = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)

添加到superview的单元与为调整大小而创建的单元具有不同的边距。因此不同。

取决于您的约束是什么。另外,这可以用表视图代替吗?@matt我已经用约束示例更新了我的问题。@matt
UItableView
在这里不是一个选项,因为
UICollectionView
有一个带有阴影、标题和分隔符的自定义布局。那么问题就来了。正如我所建议的,这是制约因素。
UIView.appearance().layoutMargins = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)