iOS + Autolayout: UITableViewCell label + textfield width with rotation

autolayout, ios, iphone, objective-c

Solution

With the help of the comments above, I've added the following to my custom UITableViewCell class:

- (void)setupLabelWidthConstraint {
    if (self.labelWidthConstraint) {
        [self.contentView removeConstraint:self.labelWidthConstraint];
    }
    if (UIDeviceOrientationIsLandscape([[UIDevice currentDevice] orientation])) {
        self.labelWidthConstraint =
        [[NSLayoutConstraint constraintsWithVisualFormat:@"[label(==width)]"
                                                 options:0
                                                 metrics:@{@"width": [NSNumber numberWithFloat:LABEL_LANDSCAPE_WIDTH]}
                                                   views:@{@"label": self.label}] lastObject];
    } else {
        self.labelWidthConstraint =
        [[NSLayoutConstraint constraintsWithVisualFormat:@"[label(==width)]"
                                                 options:0
                                                 metrics:@{@"width": [NSNumber numberWithFloat:LABEL_PORTRAIT_WIDTH]}
                                                   views:@{@"label": self.label}] lastObject];
    }
    [self.contentView addConstraint:self.labelWidthConstraint];
}

And running it in `initWithCoder:` and. Furthermore, I've added the following to my UITableViewController:

-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    NSArray *visibleCells = [self.tableView visibleCells];
    for (UITableViewCell *visibleCell in visibleCells) {
        if ([visibleCell isKindOfClass:[FMSingleInputCell class]]) {
            FMSingleInputCell *singleInputCell = (FMSingleInputCell *)visibleCell;
            [singleInputCell setupLabelWidthConstraint];
        }
    }
}

And this does the trick! (`LABEL_LANDSCAPE_WIDTH` and `LABEL_PORTRAIT_WIDTH` are defined to be `100.f` and `175.f`)

Problem

I have an issue with AutoLayout on iOS (6.x) which I don't know the answer to. I have a UITableViewCell with a UILabel and a UITextField, like this: ``` +------------------+ | label textField | +------------------+ ``` I want to use AutoLayout to layout these, but there is a caveat. The UILabel should be 100 points in portrait mode and 175 points in landscape mode. I.e. in the visual format language this would be something like the following ``` Portrait: |-[label(100)]-[textField]-| Landscape: |-[label(175)]-[textField]-| ``` So the textfield will take up the rest of the cell's view. Of course I could solve this by overwriting `willRotateToInterfaceOrientation:duration:` and figure out which cells are currently displayed and then call `updateConstraints` on them, so I can update the width of the label depending on the orientation, but that doesn't seem to be the way to go. First of all then hooking into the rotation-animation seems hard or impossible. Second of all my feeling tells me I could solve it with priorities and inequalities. I would add something like `[label(>=100,<=175)]` for the label, but then I need to do something else, because otherwise the label will always be sized to a particular size (either 100 or 175). I thought I had fixed it: I had set the content hugging priority of the label to 200, set a constraint on the text field that the width should be at least 152 and then it does what I want, unless I for example enable editing mode of the table view, because then the textfield can't be 152 points wide anymore (there is not enough space). Entering this arbitrary "152" also feels like not the way to go. So does anyone have any suggestions how I could fix this?

Original source