带有自动布局的UITableViewCell - contentView宽度约束失败

13

我在iOS 8中遇到了一个动态大小的tableViewCell问题。虽然它在视觉上看起来很好,但是我收到了AutoLayout错误的日志输出。我已经将其简化为这个简单的例子。

我正在向我的单元格添加一个UILabel:

self.titleLabel = [[UILabel alloc] init];
self.titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
self.titleLabel.numberOfLines = 0;
self.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
[self.contentView addSubview:self.titleLabel];

我正在使用Masonry在代码中创建自动布局约束,在updateConstraints方法中:

[self.titleLabel setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
[self.titleLabel updateConstraints:^(MASConstraintMaker *make) {
    make.leading.equalTo(self.contentView.leading).with.offset(padding.left);
    make.trailing.equalTo(self.contentView.trailing).with.offset(-padding.right);
    make.top.equalTo(self.contentView.top).with.offset(padding.top);
    make.bottom.equalTo(self.contentView.bottom).with.offset(-padding.bottom / 2);
}];

(我可以使用make.edges一步完成此操作,但问题是一样的)

一开始看起来很好,也能够正常工作。然而,当我对tableview进行任何修改并调用[tableView endUpdates](应该会触发updateContraints),我在控制台日志中看到以下内容:

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) 
(
    "<MASLayoutConstraint:0x7ff4842551e0 UILabel:self.titleLabel.leading == UITableViewCellContentView:self.contentView.leading + 12>",
    "<MASLayoutConstraint:0x7ff484255240 UILabel:self.titleLabel.trailing == UITableViewCellContentView:self.contentView.trailing - 12>",
    "<NSLayoutConstraint:0x7ff484256df0 UITableViewCellContentView:self.contentView.width ==>"
)

Will attempt to recover by breaking constraint 
<MASLayoutConstraint:0x7ff484255240 UILabel:self.titleLabel.trailing == UITableViewCellContentView:self.contentView.trailing - 12>

我不明白这里的问题是什么——我想让标签有填充,但为什么会与contentView的整体宽度冲突?

编辑1:

如果我删除填充,就不会再出现错误了。有没有其他方法可以设置它?


你尝试过使用可视化格式吗?NSArray *formats = @[ @"H:|-12-[tl]-12-|", @"V:|-6-[tl]-6-|" ]; 然后可能将其应用于内容视图? - Mike Welsh
感谢您查看我的问题!不幸的是,使用视觉格式语言会导致与上述完全相同的错误。 :/ - blork
这有帮助吗?http://derpturkey.com/autosize-uitableviewcell-height-programmatically/ - Mike Taverne
尝试降低self.contentView.width的压缩阻力。单元格正在尝试缩小或增大宽度,但cell.contentView的宽度设置为保持在某个宽度上。 - Brooks Hanes
我已经尝试过使用UILayoutPriorityDefaultLow(以及required和中间的所有常量)来解决UILayoutConstraintAxisHorizontal的问题 - 但都遇到了相同的困扰。 - blork
显示剩余5条评论
3个回答

3

您拥有三个相同优先级的限制条件,这使得系统不知道如何同时满足它们。

由于单元格的宽度也根据设备宽度固定,因此建议将子视图的约束条件优先级稍微降低。

[self.titleLabel updateConstraints:^(MASConstraintMaker *make) {
    make.leading.equalTo(self.contentView.leading).with.offset(padding.left).priority(999);
    make.trailing.equalTo(self.contentView.trailing).with.offset(-padding.right).priority(999);
    make.top.equalTo(self.contentView.top).with.offset(padding.top);
    make.bottom.equalTo(self.contentView.bottom).with.offset(-padding.bottom / 2);
}];

简直不敢相信我之前没试过,但是重新开始对我来说非常好。终于,谢谢! - blork

1
根据您的问题,我发现您已经在xib或storyboard中的自定义单元格中放置了标签,当您尝试手动设置约束时,它与您程序中设置的约束不匹配。因此,我建议您通过编程方式创建标签并应用约束。
您还可以访问:通过编程方式创建布局约束 编辑1:
尝试查看此链接,它可能对您有所帮助,并且可能解决您面临的问题。
http://captechconsulting.com/blog/tyler-tillage/ios-8-tutorial-series-auto-sizing-table-cells

晚回复 - 这个单元格不是从nib或storyboard中获取的,而是完全由代码编写的。我尝试使用nib,但仍然遇到了相同的错误。 - blork
抱歉回复晚了。请访问链接,它可能会有所帮助,尽管约束已在Storyboard中设置,但可以通过编码进行类似设置。 http://www.appcoda.com/self-sizing-cells/ - Dhaivat Vyas

1

在使用动态单元格高度计算之前,您是否已配置了UITableView?我遇到了非常相似的问题,这段代码对我很有帮助

- (void)viewDidLoad {
  [super viewDidLoad];
  self.tableView.estimatedRowHeight = 150;
  self.tableView.rowHeight = UITableViewAutomaticDimension;
}

我没有使用过Masonry框架,但标准的约束对我来说很好用。也许你在使用Masonry格式时出现了一些问题?
    self.titleLabel = [[UILabel alloc] init];
    self.titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
    self.titleLabel.numberOfLines = 0;
    self.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
    [self.contentView addSubview:self.titleLabel];
    NSArray *constraintsHorizontal = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-12-[_titleLabel]-12-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_titleLabel)];
    NSArray *constraintsVertical = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-12-[_titleLabel]-12-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_titleLabel)];
    [self.contentView addConstraints:constraintsHorizontal];
    [self.contentView addConstraints:constraintsVertical];

请查看测试项目,链接地址为https://dl.dropboxusercontent.com/u/48223929/TestTableCellsAutolayout.zip


是的,我非常确定我已经正确配置了它。我在我的viewDidLoad中有这个完全相同的代码(尽管我的高度为100)。 - blork
我尝试通过标准约束构造函数来实现它,对我来说它有效。我认为Masorny框架可能存在问题。 - Vitalii Gozhenko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接