UITableViewCell 的 NSLayoutConstraint:约束必须包含第一个布局项

Posted

技术标签:

【中文标题】UITableViewCell 的 NSLayoutConstraint:约束必须包含第一个布局项【英文标题】:NSLayoutConstraint for UITableViewCell: Constraint must contain a first layout item 【发布时间】:2017-12-13 14:45:13 【问题描述】:

我正在尝试在我的每个自定义单元格(继承自 UITableViewCell)中设置 NSLayoutConstraint,而不是在 UIViewController 中指定它们,以避免通过公开每种单元格类型的约束来使其混乱。

问题是我找不到单元格生命周期的适当部分来创建布局约束(我尝试了layoutSubviews()awakeFromNib()),但是它们都在单元格的生命周期中被调用得太早,当它的@ 987654327@ 尚未定义 - 它会导致此错误:

约束必须包含第一个布局项

既然UITableViewCell 没有viewDidLoad()UIViewController 这样的方法,那么如何定义单元格内的布局约束?

layoutSubviews()的自定义UITableViewCell

- (void) layoutSubviews 
    self.translatesAutoresizingMaskIntoConstraints = false;
    [[NSLayoutConstraint constraintWithItem: self.attributeNameLabel
                                  attribute: NSLayoutAttributeLeading
                                  relatedBy: NSLayoutRelationEqual
                                     toItem: self.contentView
                                  attribute: NSLayoutAttributeLeading
                                 multiplier: 1
                                   constant: 3] setActive:true];
    [[NSLayoutConstraint constraintWithItem: self.attributeNameLabel
                                  attribute: NSLayoutAttributeTop
                                  relatedBy: NSLayoutRelationEqual
                                     toItem: self.contentView
                                  attribute: NSLayoutAttributeTop
                                 multiplier: 1
                                   constant: 3] setActive:true];
    [[NSLayoutConstraint constraintWithItem: self.attributeNameLabel
                                  attribute: NSLayoutAttributeRight
                                  relatedBy: NSLayoutRelationEqual
                                     toItem: self.contentView
                                  attribute: NSLayoutAttributeRight
                                 multiplier: 1
                                   constant: 3] setActive:true];
    [[NSLayoutConstraint constraintWithItem: self.attributeNameLabel
                                  attribute: NSLayoutAttributeBottom
                                  relatedBy: NSLayoutRelationEqual
                                     toItem: self.contentView
                                  attribute: NSLayoutAttributeBottom
                                 multiplier: 1
                                   constant: 3] setActive:true];   

UIViewController 中的示例初始化:

- (UITableViewCell *)tableView:(UITableView *)view cellForRowAtIndexPath:(NSIndexPath *)indexPath 
    UITableViewCell *cell;

    if (indexPath.row % 2 == 0) 
        cell = [[CustomCell1 alloc] init];
     else if (indexPath.row % 2 == 1) 
        cell = [[CustomCell2 alloc] init];
     else if (...) 
        ...
    
    return cell;

【问题讨论】:

你没有使用xib或storyboard? 我不想使用故事板,因为我有许多不同的单元格类型(具有继承等)......它很快就会变得混乱 你有没有在设置约束后尝试过updateConstraintsIfNeeded()? 不,我不能,应用程序甚至没有设置第一个约束。它在这一行崩溃:[[NSLayoutConstraint constraintWithItem:... 尝试使用锚点。它更清洁。见here 【参考方案1】:

尝试制作

 self.attributeNameLabel.translatesAutoresizingMaskIntoConstraints = NO;

对于每个标签而不是 contentView

将它们转换成对我有用的方式

这样做

  - (void)awakeFromNib 
// Initialization code



[super awakeFromNib];


UILabel*ddd = [UILabel new];

ddd.text = @"adsbcujklasdcbaksci";

ddd.translatesAutoresizingMaskIntoConstraints = NO ;

[self.contentView addSubview:ddd];

 NSLayoutConstraint*ss1 =  [NSLayoutConstraint constraintWithItem: ddd
                              attribute: NSLayoutAttributeCenterX
                              relatedBy: NSLayoutRelationEqual
                                 toItem: self.contentView
                              attribute: NSLayoutAttributeCenterX
                             multiplier: 1 constant: 3] ;
NSLayoutConstraint*ss2 =  [NSLayoutConstraint constraintWithItem: ddd
                              attribute: NSLayoutAttributeCenterY
                              relatedBy: NSLayoutRelationEqual
                                 toItem: self.contentView
                              attribute: NSLayoutAttributeCenterY
                             multiplier: 1   constant: 3]  ;

 [self.contentView addConstraints:@[ss1,ss2]];



 [self layoutSubviews];

 [self layoutIfNeeded];




【讨论】:

在这种情况下需要哪些元素?在此示例中,我仅访问 self.contentViewself.attributeNameLabel,但仍然收到有关缺少第一个布局项的错误。 在你的函数末尾添加上面两行 仅此一项不起作用,同样的错误。顺便说一句,我打电话给layoutSubviews() 没有问题。它会自动调用,而不会将其添加到函数的末尾。 这行得通,在接受答案之前我必须仔细查看它。

以上是关于UITableViewCell 的 NSLayoutConstraint:约束必须包含第一个布局项的主要内容,如果未能解决你的问题,请参考以下文章

我们如何测量 Cocoa 中文本的可见边界?

重用 tableviewcell 中的约束和高度未更新

视觉格式化语言、按钮宽度和高度约束

UIScrollView 右侧的 Autolayout Pin 视图

突出显示的 UITableViewCell 和选定的 UITableViewCell 有啥区别?

UITableViewCell 中的 UIDatePicker 更新 UITableViewCell 文本标签