where to create autolayout constraints for subclassed uitableviewcell?
Asked Answered
M

1

16

I am trying to use autolayout for a uitableviewcell subclass I am creating and I would appreciate some advice on what method to put the layout constraint creation code. I have been searching around and all the information I find talks about adding constraints after adding subviews in the viewDidLoad method. As far as I know viewDidLoad isn't an option for a uitableviewcell subclass.

I am using interface builder to create a custom cell and dynamically allocating it in my code. Nothing special there... I subclass the uitableviewcell so I can add a custom uiview to the cell. Again, nothing particularly Earth shattering... My difficulty comes when I try to position my custom uiview with respect to a label I added to the cell in interface builder.

This is the code to create the custom uiview and add it to the cell's content view:

- (id)initWithCoder:(NSCoder *)decoder
{
    if ((self = [super initWithCoder:decoder]))
    {
        [self initSelf];
    }
    return self;
}

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    if ((self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]))
    {
        [self initSelf];
    }
    return self;
}

- (void) initSelf
{
    // Initialization code
    _badgeLabel = @"";

    if (!_customBadge)
    {
        _customBadge = [CustomBadge customBadgeWithString:self.badgeLabel];
    }

    // hide the badge until needed
    self.customBadge.hidden = YES;

    // add badge to the cell view hierarchy
    [self.customBadge setTranslatesAutoresizingMaskIntoConstraints:NO];
    [self.customBadge setContentHuggingPriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisHorizontal];
    [self.customBadge setContentHuggingPriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisVertical];

    [self.contentView addSubview:self.customBadge];
}

If I put the constraint code at the end of initSelf nothing happens. The position of my _customBadge stays at its' default. When I put the constraint code in layoutSubviews the positioning is applied; but I am pretty sure it is the wrong place. Here's the code:

- (void) layoutSubviews
{
    [self.contentView addConstraint:[NSLayoutConstraint
                                     constraintWithItem:self.customBadge
                                     attribute:NSLayoutAttributeLeft
                                     relatedBy:NSLayoutRelationEqual
                                     toItem:self.competence
                                     attribute:NSLayoutAttributeRight
                                     multiplier:1.0
                                     constant:-14.0]];

    [self.contentView addConstraint:[NSLayoutConstraint
                                     constraintWithItem:self.customBadge
                                     attribute:NSLayoutAttributeTop
                                     relatedBy:NSLayoutRelationEqual
                                     toItem:self.competence
                                     attribute:NSLayoutAttributeTop
                                     multiplier:1.0
                                     constant:0.0]];

    [super layoutSubviews];
}

Can anyone tell me where this code should go? Surely I am creating duplicate constraints every time a layout happens.

Thanks

Montcalm answered 9/4, 2013 at 6:4 Comment(0)
E
30

You would need to update constraints like:

-(void)updateConstraints{
 // add your constraints if not already there
 [super updateConstraints];
}

After adding your views to superview you need to call [self setNeedsUpdateConstraints] to start using them. By doing so the rendering runtime will call updateConstraints at the right time.

Erase answered 9/4, 2013 at 6:44 Comment(4)
The documentation (developer.apple.com/library/ios/documentation/uikit/reference/…) say, "Call [super updateConstraints] as the final step in your implementation.".Barcarole
But does this re-add the same constraints every time updateConstraints is called? Is it best practice to first remove any constraints you've previously added before adding them in again? Or is iOS wise enough to recognise that a constraint you're adding already exists and so does not add it again?Supernatural
@PapillonUK: I saw other implementations which used a bool to check if constraints has been already added. So it won't be added another time. Of course you have to remove/add/change constraints if something changes (e.g. orientation change).Weinstein
@PapillonUK's question had me wondering and @Weinstein talked about a boolean flag. More specifically, @smileyborg has addressed this issue in another SO answer. For reference I'm linking here (his response regarding updateConstraints is covered in points #1 & #2 of his accepted answer) Link: #19015715Starnes

© 2022 - 2024 — McMap. All rights reserved.