自定义 UITableViewCell 是否有一种简单的方法可以与标准 UITableViewCell 具有相同的边缘?

Is there a simple way how a custom UITableViewCell can have the same edges as a standard UITableViewCell?

我有一个带有静态内容的自定义 UITableViewCell,它有一个 UIStackView 作为内容视图的单个子视图。我希望 UIStackView 使用与 UIKit 内置的标准 UITableViewCell 相同的水平 margins/insets,跨所有 iOS 版本,从 iOS 9(我的最小部署目标)开始到当前 iOS 14,并且在 iPhone 和 iPad 设备上。

我天真地开始添加约束,将 UIStackView 的 leading/trailing 锚点附加到内容视图的 readableContentGuide。我不喜欢 Interface Builder,所以我的代码是这样的:

UIStackView stackView = [...]
[stackView.leadingAnchor constraintEqualToAnchor:self.contentView.readableContentGuide.leadingAnchor].active = YES;
[stackView.trailingAnchor constraintEqualToAnchor:self.contentView.readableContentGuide.trailingAnchor].active = YES;

这工作得很好,除了在某些情况下 (1) 标准 UITableViewCell 使用 readableContentGuide,所以将标准单元格与我的自定义单元格混合看起来不好,因为它们的边缘没有对齐。此处您看到 4 个自定义单元格,顶部和底部各有一个标准单元格:

(1) 它发生在这些场景中:

我曾尝试使用 layoutMarginsGuide 而不是 readableContentGuide,但这会导致许多约束错误(“无法同时满足约束。”在 Xcode 的调试输出中)。我也试过设置

self.tableView.cellLayoutMarginsFollowReadableWidth = YES;

在 table 视图中使用我的自定义单元格,这是有效的,因为标准单元格现在的边缘与我的自定义单元格位于同一位置。但我不喜欢这种解决方法,首先是因为这意味着我必须为每个想要使用我的自定义单元格的 table 视图进行特殊设置,其次是因为它不必要地减少了可用于数据显示的宽度.

我好像漏掉了什么。是否有一种简单、标准的方法可以如何使用布局指南来布局自定义 UITableViewCell 的内容,以便自定义单元格内容的边缘与标准单元格的边缘位于同一位置?

您应该可以使用单元格的 .contentView.layoutMarginsGuide:

UILayoutGuide *g = self.contentView.layoutMarginsGuide;

[NSLayoutConstraint activateConstraints:@[

    [stackView.topAnchor constraintEqualToAnchor:g.topAnchor],
    [stackView.leadingAnchor constraintEqualToAnchor:g.leadingAnchor],
    [stackView.trailingAnchor constraintEqualToAnchor:g.trailingAnchor],
    [stackView.bottomAnchor constraintEqualToAnchor:g.bottomAnchor],

]];

如果这给你“无法同时满足约束”的消息,但布局看起来正确——这在单元格中使用堆栈视图时很常见——你可以忽略这些消息或给予底部锚点低于要求的优先级:

UILayoutGuide *g = self.contentView.layoutMarginsGuide;

NSLayoutConstraint *c = [stackView.bottomAnchor constraintEqualToAnchor:g.bottomAnchor];
c.priority = UILayoutPriorityDefaultHigh;

[NSLayoutConstraint activateConstraints:@[

    [stackView.topAnchor constraintEqualToAnchor:g.topAnchor],
    [stackView.leadingAnchor constraintEqualToAnchor:g.leadingAnchor],
    [stackView.trailingAnchor constraintEqualToAnchor:g.trailingAnchor],
    
    c,
    
]];