0

I am trying to set NSLayoutConstraint within each of my custom cells (inherited from UITableViewCell), rather than specifying them in a UIViewController to avoid cluttering it by exposing the constraints for each cell type.

The problem is that I could not find an appropriate part of the cell's lifecycle to create the layout constraints (I tried layoutSubviews() and awakeFromNib()), but they all get called too early in the cell's lifecycle, when its superview has not been defined yet - it results in this error:

Constraint must contain a first layout item

Since UITableViewCell does not have the viewDidLoad() method like the UIViewController, how is it possible to define the layout constraints within the cell?

layoutSubviews() of the custom 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];   
}

Example initialization in 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;
}
Peter G.
  • 7,816
  • 20
  • 80
  • 154

1 Answers1

2

try to make

 self.attributeNameLabel.translatesAutoresizingMaskIntoConstraints = NO;

for every label not the contentView

convert them like that it worked for me

do this

  - (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];



}
Shehata Gamal
  • 98,760
  • 8
  • 65
  • 87
  • What would be the required elements in this case? I'm only accessing `self.contentView` and `self.attributeNameLabel` in this example, but still getting error about missing first layout item. – Peter G. Dec 13 '17 at 15:00
  • add the above two lines at the end of your function – Shehata Gamal Dec 13 '17 at 15:07
  • This alone doesn't work, same error. Btw I am not having problems calling the `layoutSubviews()`. It gets called automatically without adding it to the end of the function. – Peter G. Dec 13 '17 at 15:09
  • This works, I have to look at it closely before accepting the answer. – Peter G. Dec 13 '17 at 15:19