Autolayout programmatically on a subview of a subclassed UIView

brucemartin picture brucemartin · Nov 20, 2012 · Viewed 13.9k times · Source

I have subclassed UIView to make a custom groupView I use to add a few things to my layout in a simple way. This groupView includes a UILabel which is used as a heading and a UIView that draws a roundRect on it's CALayer with a background color. Think UITableView's sections. I add this groupView to the storyboard by dropping a UIView and changing it's class to my subclass. All works well, I set the heading via the User defined runtime attributes in Xcode. All works great, I add UILabels to this view on the storyboard and it creates the heading label and roundrect when it runs.

structure of my groupView:

  1. groupView: (UIView)clipToBounds:NO;
    • heading: (UILabel) positioned above the groupView.
    • contentView:(UIView) creates the roundRect and color via CALayer, should be same size as the groupView.

So what's the problem? Well, dealing with autolayout is a pain to begin with, but for this subclassed UIView to work I need to set the contentView constraints programmatically. I can't figure out the syntax of this auto layout ASCII format string. Currently I have:

 _contentView = [[UIView alloc]initWithFrame:self.bounds];

    _contentView.layer.cornerRadius = 5.0f;
    _contentView.layer.masksToBounds=YES;
    _contentView.backgroundColor=_backgroundColor;
    _contentView.layer.borderWidth=_borderWidth;
    _contentView.layer.borderColor=_borderColor.CGColor;
    [self insertSubview:_contentView atIndex:0];
    NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(self,_contentView);
    NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"[self]-0-[_contentView]-0-[self]" options:0 metrics:nil views:viewsDictionary];

    for (NSLayoutConstraint *constraint in constraints) {
        [_contentView addConstraint:constraint];
    }

Which crashes with: * Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to install constraint on view. Does the constraint reference something from outside the subtree of the view? That's illegal. constraint: view:>'

I tried this first and it still didn't work:

    NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(_contentView);
    NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"|-0-[_contentView]-0-|" options:0 metrics:nil views:viewsDictionary];

Which crashes with: * Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to install constraint on view. Does the constraint reference something from outside the subtree of the view? That's illegal. constraint: view:>'

RANT: Somehow this AutoLayout is suppose to save us work, but I do not see how the benefits out weight the overhead right now. Why on earth did they move from using references and methods or even type defs to this archaic format string? How much easier would it be to do: [_contentView constraint:NSLayoutFormatAlignLeading toView:self withDistance:0.0f]; OR something similar? I would so much rather deal with springs and struts at this point.

Any help understanding, or showing me the syntax to constrain the contentView to the size of self would be helpful.

Answer

jackslash picture jackslash · Nov 20, 2012

The error tells you what you need to know:

Does the constraint reference something from outside the subtree of the view?

Yes it does. It references its superview.

These constraints you are making need to be applied to the superview, in this case the groupView.