2

I'm using the Masonry pod to control my constrains on my UI elements in a tableView, and my view extends UITableViewCell. I have three UI elements per cell, displaying ratings and reviews of popular cruise ports. One of the elements is removed and replaced depending on whether the port has been rated.

Prior to maybe a week ago, the UILabel for the review was displaying without any additional padding, but now it displays with what appears to be 2 additional lines worth of padding on the top and bottom of the UILabel.

Here's the relevant code:

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
        self.rating = 0;

        //solves autolayout error http://stackoverflow.com/questions/19132908/auto-layout-constraints-issue-on-ios7-in-
//        self.contentView.bounds = CGRectMake(0, 0, 99999, 99999);
        // description label
        self.descriptionLabel = [[UILabel alloc] init];
        [self.descriptionLabel setPreferredMaxLayoutWidth:self.contentView.bounds.size.width];
        [self.descriptionLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
        [self.descriptionLabel setFont:[UIFont fontWithName:[StringFactory defaultFontType] size:14.0f]];
        [self.descriptionLabel setTextColor:[ColorFactory CC333]];
        [self.descriptionLabel setNumberOfLines:0];
        [self.descriptionLabel sizeToFit];
        // Without this, it can happen that the last line of the text to be displayed can be cut, although
        // all the proper constraints seem to be set correctly.
        [self.descriptionLabel setAdjustsFontSizeToFitWidth:NO];
        [self.descriptionLabel setBackgroundColor:[ColorFactory CCOrange]];
        [self.contentView addSubview:self.descriptionLabel];


        // create date label
        self.dateLabel = [[UILabel alloc] init];
        [self.dateLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
        [self.dateLabel setFont:[UIFont fontWithName:[StringFactory defaultFontType] size:14.0f]];
        [self.dateLabel setTextColor:[ColorFactory CC333]];
        [self.contentView addSubview:self.dateLabel];

        //create ratingView
        self.ratingView = [[UIImageView alloc] init];
        [self.ratingView setTranslatesAutoresizingMaskIntoConstraints:NO];
        [self.contentView addSubview:self.ratingView];

        // create ratingLabel
        self.ratingLabel = [[UILabel alloc] init];
        [self.ratingLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
        [self.ratingLabel setFont:[UIFont fontWithName:[StringFactory defaultBoldFontType] size:14.0f]];
        [self.ratingLabel setTextColor:[ColorFactory CC333]];
        [self.contentView addSubview:self.ratingLabel];

        self.contentView.backgroundColor = [UIColor whiteColor];

        // add KVO to update cell
        [self addObserver:self forKeyPath:@"portReview" options:NSKeyValueObservingOptionNew context:nil];

        //Add constraints
        [self setLayout];
    }

    return self;
}

- (void)dealloc {
    [self removeObserver:self forKeyPath:@"portReview" context:nil];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if ([keyPath isEqualToString:@"portReview"]) {
        [self configureCell];
    }
}

- (void)configureCell {
    self.descriptionLabel.text = self.portReview.review;

    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setTimeZone: [NSTimeZone timeZoneWithAbbreviation:@"EST"]];
    [dateFormatter setDateFormat:[StringFactory shortDateFormat]];
    NSMutableString *authorString = [NSMutableString stringWithString:@""];
    if (self.portReview.author != nil)
    {
        authorString = [NSMutableString stringWithFormat:@"(%@)", self.portReview.author];
    }
    self.dateLabel.text = [NSString stringWithFormat:@"%@ %@", [dateFormatter stringFromDate:self.portReview.createdAt], authorString];

    // Rating can never exceed 5 bubbles. In case the rating provided is greater than 5, round down to 5.
    CGFloat roundedRating = MIN(round([self.portReview.rating floatValue] * 2) / 2, 5.0f);
    roundedRating = MAX(0, roundedRating);

    self.rating = roundedRating;

    if (self.rating > 0)
    {
        [self.contentView addSubview:self.ratingView];
        [self.ratingView setImage:[UIImage imageNamed:[NSString stringWithFormat:@"cc_bubbles_%.1f.png", roundedRating]]];
        if ([self.ratingLabel isDescendantOfView:self.contentView])
        {
            [self.ratingLabel removeFromSuperview];
        }
        if (self.ratingLabel.constraints)
        {
            [self.ratingLabel removeConstraints:self.ratingLabel.constraints];
        }
    }
    else
    {
        [self.contentView addSubview:self.ratingLabel];
        [self.ratingLabel setText:@"Not Rated"];
        if ([self.ratingView isDescendantOfView:self.contentView])
        {
            [self.ratingView removeFromSuperview];
        }
        if (self.ratingView.constraints)
        {
            [self.ratingView removeConstraints:self.ratingView.constraints];
        }
    }

    [self setLayout];
}

-(void)setLayout
{
    typeof (self) __weak weakSelf = self;

    // rating
    if (self.rating > 0)
    {
        [self.ratingView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(weakSelf.contentView.mas_top).with.offset(kPadding);
            make.left.equalTo(weakSelf.contentView.mas_left).with.offset(kPadding);
            make.height.equalTo(@20);
            make.width.equalTo(@100);
        }];
    }
    else
    {
        [self.ratingLabel mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(weakSelf.contentView.mas_top).with.offset(kPadding);
            make.left.equalTo(weakSelf.contentView.mas_left).with.offset(kPadding);
            make.height.equalTo(@20);
            make.width.equalTo(@100);
        }];
    }

    // date label
    [self.dateLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        if (weakSelf.rating > 0)
        {
            make.top.equalTo(weakSelf.ratingView.mas_bottom).with.offset(kPadding);
        }
        else
        {
            make.top.equalTo(weakSelf.ratingLabel.mas_bottom).with.offset(kPadding);
        }
        make.left.equalTo(weakSelf.contentView.mas_left).with.offset(kPadding);
        make.right.equalTo(weakSelf.contentView.mas_right).with.offset(-kPadding);
    }];

    // description
    [self.descriptionLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(weakSelf.dateLabel.mas_bottom).with.offset(kPadding);
        make.left.equalTo(weakSelf.contentView.mas_left).with.offset(kPadding);
        make.right.equalTo(weakSelf.contentView.mas_right).with.offset(-kPadding);
        make.bottom.equalTo(weakSelf.contentView.mas_bottom).with.offset(-kPadding);
    }];
}

And the output (background is orange to highlight the padding):

Screen cap

Why does auto layout add this padding, and how can I get rid of it? It crops up in other areas of the app, as well, so I'd like to understand why it's happening so I can fix the undesired layout.

Edit:

The height is calculated for each row in tableView:heightForRowAtIndexPath as follows:

PortReviewTableViewCell* cell = self.autoLayoutCell;
cell.portReview = self.portReviews[indexPath.row];

// Since we have multi-line labels, do an initial layout pass and then set the preferredMaxLayoutWidth
// based on their width so they will wrap text and take on the correct height
[cell.contentView setNeedsLayout];
[cell.contentView layoutIfNeeded];
cell.descriptionLabel.preferredMaxLayoutWidth = CGRectGetWidth(cell.descriptionLabel.frame);

CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;

return height;
Matt
  • 6,993
  • 4
  • 29
  • 50

0 Answers0