Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Applying NSLayoutConstraints to a UIView subclass

I've tried using AutoLayout constraints in IB before and I understand how they work and that they need to be unambiguous etc...

But when you have more than a couple of views it gets a bit complicated and tends to break.

So, I've just read a blog about a guy having the same problem and using ASCII code to create the constraints instead.

I have a UITableView with a custom UITableViewCell that has a dynamic size based on the amount of content. A perfect candidate for auto layout.

So, I've tried several ways of doing it and now I've cut down the content so that there's only a single label in the cell.

What I would like if for the label to fill the cell with a border around it.

i.e. standard size points in from each edge of the cell.

I've done it like this...

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        _label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
        _label.textColor = [UIColor colorWithWhite:0.53 alpha:1.0];
        _label.backgroundColor = [UIColor yellowColor];
        [self addSubview:_label];

        NSDictionary *views = NSDictionaryOfVariableBindings(_label);

        [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[_label]-|"
                                                                     options:0
                                                                     metrics:nil
                                                                       views:views]];

        [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|-[_label]-|"
                                                                     options:0
                                                                     metrics:nil
                                                                       views:views]];

        self.backgroundView = [[UIView alloc] initWithFrame:CGRectZero];
        self.backgroundColor = [UIColor clearColor];
    }
    return self;
}

But when the cell is displayed the label is in the top left hand corner exactly like the CGRect I used to init it and I get this load of errors about the constraints...

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) 
(
    "<NSAutoresizingMaskLayoutConstraint:0x1f859e40 h=--& v=--& UILabel:0x1f864a00.midX == + 5>",
    "<NSLayoutConstraint:0x1f86a4f0 H:|-(NSSpace(20))-[UILabel:0x1f864a00]   (Names: '|':MyCell:0x1f857740 )>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x1f86a4f0 H:|-(NSSpace(20))-[UILabel:0x1f864a00]   (Names: '|':MyCell:0x1f857740 )>

Break on objc_exception_throw to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
2013-03-07 11:56:14.841 unasys[13082:907] 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) 
(
    "<NSLayoutConstraint:0x1f85f7b0 V:|-(NSSpace(20))-[UILabel:0x1f864a00]   (Names: '|':MyCell:0x1f857740 )>",
    "<NSAutoresizingMaskLayoutConstraint:0x1f859ec0 h=--& v=--& UILabel:0x1f864a00.midY == + 5>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x1f85f7b0 V:|-(NSSpace(20))-[UILabel:0x1f864a00]   (Names: '|':MyCell:0x1f857740 )>

Break on objc_exception_throw to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
2013-03-07 11:56:14.854 unasys[13082:907] 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) 
(
    "<NSLayoutConstraint:0x1f86a540 H:[UILabel:0x1f864a00]-(NSSpace(20))-|   (Names: '|':MyCell:0x1f857740 )>",
    "<NSAutoresizingMaskLayoutConstraint:0x1f859e40 h=--& v=--& UILabel:0x1f864a00.midX == + 5>",
    "<NSAutoresizingMaskLayoutConstraint:0x1f859e80 h=--& v=--& H:[UILabel:0x1f864a00(10)]>",
    "<NSAutoresizingMaskLayoutConstraint:0x1ed8e150 h=--& v=--& H:[MyCell:0x1f857740(320)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x1f86a540 H:[UILabel:0x1f864a00]-(NSSpace(20))-|   (Names: '|':MyCell:0x1f857740 )>

Break on objc_exception_throw to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
2013-03-07 11:56:14.858 unasys[13082:907] 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) 
(
    "<NSAutoresizingMaskLayoutConstraint:0x1eda7260 h=--& v=--& V:[MyCell:0x1f857740(143)]>",
    "<NSAutoresizingMaskLayoutConstraint:0x1f859f00 h=--& v=--& V:[UILabel:0x1f864a00(10)]>",
    "<NSLayoutConstraint:0x1f85f870 V:[UILabel:0x1f864a00]-(NSSpace(20))-|   (Names: '|':MyCell:0x1f857740 )>",
    "<NSAutoresizingMaskLayoutConstraint:0x1f859ec0 h=--& v=--& UILabel:0x1f864a00.midY == + 5>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x1f85f870 V:[UILabel:0x1f864a00]-(NSSpace(20))-|   (Names: '|':MyCell:0x1f857740 )>

and I've got no idea where to start with debugging this. The constraints are absolutely minimal but still it completely fails.

Can someone point me in the right direction of how to get this constraint to work?

like image 461
Fogmeister Avatar asked Mar 07 '13 12:03

Fogmeister


1 Answers

After the line

_label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];

add

[_label setTranslatesAutoresizingMaskIntoConstraints:NO];

By default the autoresizingmask is also turned into constraints, which conflicts with the constraints you've set, making it ambigious

The docs are here: setTranslatesAutoresizingMaskIntoConstraints

like image 157
iain Avatar answered Oct 05 '22 23:10

iain