ios - 为什么 UITableViewCell 有自动布局约束冲突

标签 ios objective-c cocoa-touch uitableview autolayout

我有一个 UITableViewSubclass(样式:UITableViewCellStyleValue1),它有一个自定义标签,本质上是普通 textLabel 标签的替代品。它应该与普通 textLabel 左对齐,但宽度在普通 detailTextLabel 左侧结束 8 磅。我得到了预期的效果,但是当使用单元格时,会抛出一个异常,提示无法同时满足约束条件。

我不明白的是为什么它会提示,没有明显的冲突。设置约束后调用 [self layoutIfNeeded] 会消除异常。或者,降低配置尾随属性的约束的优先级(例如,UILayoutPriorityDefaultHigh 而不是默认的 UILayoutPriorityRequired)也会使异常静音,显然是因为我正在通知自动布局引擎,可以打破/忽略该约束。

我假设标准 UITableView 实现可能奇怪地以一种最初无法描述所描述 View 的方式布置 textLabeltextLabel。例如,如果 textLabel 实际上放在单元格的右侧,而 detailTextLabel 放在左侧,那么我所描述的布局就不可能实现。

Auto Layout什么时候生效,在这个场景的上下文中。它是否抢先一步并试图在它应该做的事情之前进行布局?

没有使用 Storyboard或 XIB。完全基于代码。

#import "EBTStoreTableViewCell.h"

@interface EBTStoreTableViewCell ()
@property (nonatomic, readonly, weak) UILabel *storeNameLabel;
@end

@implementation EBTStoreTableViewCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:reuseIdentifier];
    if (self) {
        self.textLabel.text = @" ";

        self.detailTextLabel.text = @" ";

        UILabel *storeNameLabel = [[UILabel alloc] init];
        storeNameLabel.translatesAutoresizingMaskIntoConstraints = NO;
        [storeNameLabel setContentCompressionResistancePriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal];
        [self.contentView addSubview:storeNameLabel];
        _storeNameLabel = storeNameLabel;

        [self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:storeNameLabel attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.textLabel attribute:NSLayoutAttributeLeading multiplier:1.0f constant:0.0f]];
        [self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:storeNameLabel attribute:NSLayoutAttributeBaseline relatedBy:NSLayoutRelationEqual toItem:self.textLabel attribute:NSLayoutAttributeBaseline multiplier:1.0f constant:0.0f]];

        [self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:storeNameLabel attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.detailTextLabel attribute:NSLayoutAttributeLeading multiplier:1.0f constant:-8.0f]];

//        [self layoutIfNeeded]; // doing this makes the issue go away
    }
    return self;
}

// Setters ommited

@end

这是我收到的异常消息:

2014-04-23 11:50:42.092 Application[32507:60b] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSLayoutConstraint:0xde03910 UILabel:0xde036b0.leading == UILabel:0xde00590.leading>",
    "<NSLayoutConstraint:0xde03a30 UILabel:0xde036b0.trailing == UITableViewLabel:0xde00c10.leading - 8>",
    "<NSAutoresizingMaskLayoutConstraint:0xde01920 h=--& v=--& UILabel:0xde00590.midX ==>",
    "<NSAutoresizingMaskLayoutConstraint:0xde1de50 h=--& v=--& H:[UILabel:0xde00590(0)]>",
    "<NSAutoresizingMaskLayoutConstraint:0x17f50a10 h=--& v=--& UITableViewLabel:0xde00c10.midX ==>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0xde03a30 UILabel:0xde036b0.trailing == UITableViewLabel:0xde00c10.leading - 8>

Break on objc_exception_throw to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

最佳答案

您不应混合使用 textLabeldetailTextLabel。这些不能被限制,因为它们的大小是在内部管理的,并且可能会产生意想不到的结果。

您应该创建自己的标签,然后对其施加约束。

来自 UITableViewCell 的文档:

When creating cells, you can customize them yourself or use one of several predefined styles. The predefined cell styles are the simplest option. With the predefined styles, the cell provides label and image subviews whose positions and styling are fixed. All you have to do is provide the text and image content to go into those fixed views. To use a cell with a predefined style, initialize it using the initWithStyle:reuseIdentifier: method or configure the cell with that style in Xcode. To set the text and images of the cell, use the textLabel, detailTextLabel, and imageView properties.

If you want to go beyond the predefined styles, you can add subviews to the contentView property of the cell. When adding subviews, you are responsible for positioning those views and setting their content yourself.

关于ios - 为什么 UITableViewCell 有自动布局约束冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23252900/

相关文章:

ios - 将应用程序提交到应用程序商店错误

iphone - 如何水平自动拉伸(stretch) UISegmented Control 以填充完整的 UITableViewCell?

iphone - 显示来自服务器的实时位置数据

ios - 具有多个嵌入 segues 的 ContainerView

iphone - VFR 阅读器在 IOS 7 中崩溃

c - 文件(尤其是音频文件)在内部是如何组织的?

ios - 如何将触摸分配给两个 CCColorLayer?

iphone - 保存到 iPhone 的文件名有哪些限制?

cocoa-touch - 使用通知中心重新加载 UITableView 可以吗?

iphone - 数据源方法在 iOS 4.3 中不调用,但在 iOS 5 及更高版本中工作