3
votes

I'm updating my app for iOS8 and noticed a change of behavier with [NSLayoutConstraint constraintWithItem: ..].

This works fine in iOS7, but in iOS8 having a constraint with a view that is a nested subview is not working correctly.

NSLayoutConstraint *myConstraint = [NSLayoutConstraint constraintWithItem:myView.mySubview.label attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:label2 attribute:NSLayoutAttributeBottom multiplier:1.0 constant:10.0];

Essentially, it looks like because myView.mySubview.label y coordinates are 0 within it's immediate superview (mySubview), it places label2 with respect to y=0. However the top most parent view (myView) has an arbitrary y coordinate that the constraint is not respecting. It's as if Autolayout is just taking the y coordinate of the view within its immediate superview and not in context of everything. Again this same line works fine in iOS7.

If I apply the constraint to just top level views:

NSLayoutConstraint *myConstraint = [NSLayoutConstraint constraintWithItem:label1 attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:label2 attribute:NSLayoutAttributeBottommultiplier:1.0 constant:10.0];

This works fine on iOS7 and 8.

New behavior or iOS8 bug?

1
Did you report this? What's the radar number on it? What did Apple say?Paul Cezanne
Looks to be fixed with iOS8 GM.paranoidroid

1 Answers

3
votes

Seems like an iOS8 bug... it's affecting my project as well. Reproducible with the following bit of code, where I can see notWorkingLabel in iOS7 but not iOS8:

#import "ViewController.h"

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    UIView *container = [UIView new];
    container.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:container];

    UILabel *workingLabel = [UILabel new];
    workingLabel.backgroundColor = [UIColor lightGrayColor];
    workingLabel.translatesAutoresizingMaskIntoConstraints = NO;
    workingLabel.text = @"This is a visible label";
    workingLabel.font = [UIFont systemFontOfSize:20];
    [container addSubview:workingLabel];

    UIView *subContainer = [UILabel new];
    subContainer.backgroundColor = [UIColor yellowColor];
    subContainer.translatesAutoresizingMaskIntoConstraints = NO;
    [container addSubview:subContainer];

    UILabel *notWorkingLabel = [UILabel new];
    notWorkingLabel.backgroundColor = [UIColor lightGrayColor];
    notWorkingLabel.translatesAutoresizingMaskIntoConstraints = NO;
    notWorkingLabel.text = @"This label is not visible";
    notWorkingLabel.font = [UIFont systemFontOfSize:20];
    [subContainer addSubview:notWorkingLabel];

    NSDictionary *views = NSDictionaryOfVariableBindings(container, workingLabel, subContainer, notWorkingLabel);
    [subContainer addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[notWorkingLabel]-|" options:0 metrics:nil views:views]];
    [subContainer addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[notWorkingLabel]-|" options:0 metrics:nil views:views]];
    [container addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[workingLabel]|" options:0 metrics:nil views:views]];
    [container addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[subContainer]|" options:0 metrics:nil views:views]];
    [container addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-50-[workingLabel]-20-[subContainer]" options:0 metrics:nil views:views]];
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[container]|" options:0 metrics:nil views:views]];
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[container]|" options:0 metrics:nil views:views]];
}

@end