0

我开始以编程方式使用自动布局和约束,但我不明白为什么会收到以下警告

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:0x7fbbd142ead0 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7fbbd162ec70(44)]>",
    "<NSLayoutConstraint:0x7fbbd1431740 V:|-(20)-[UILabel:0x7fbbd174e520'Liked']   (Names: '|':UITableViewCellContentView:0x7fbbd162ec70 )>",
    "<NSLayoutConstraint:0x7fbbd1431790 V:[UILabel:0x7fbbd174e520'Liked']-(NSSpace(8))-[UILabel:0x7fbbd174e7e0's']>",
    "<NSLayoutConstraint:0x7fbbd14317e0 V:[UILabel:0x7fbbd174e7e0's']-(20)-|   (Names: '|':UITableViewCellContentView:0x7fbbd162ec70 )>"
)

我知道导致错误的代码行是:

constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[nameLbl]-[notificationLbl]-[textLabel]-20-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:views];

但我不明白为什么不能满足约束。这可能是一个愚蠢的问题,但我是自动布局的新手,而且由于文档不完整,这个话题令人困惑。我尝试了不同的变体和解决方案,但未能找到正确的。我错过了什么?我还粘贴了我的自定义表格视图单元格的代码以进行更详细的检查。

@implementation NotificationCell
@synthesize nameLbl,notificationLbl,textLabel,timeLbl,profileImgView,notificationImgView,clockImgView,didSetupConstraints;
-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {


        nameLbl = [[UILabel alloc]init];
        [nameLbl setTextColor:[UIColor blueColor]];
        nameLbl.translatesAutoresizingMaskIntoConstraints = NO;
        [nameLbl setTextAlignment:NSTextAlignmentLeft];
        [nameLbl setNumberOfLines:1];

        [nameLbl setBackgroundColor:[UIColor redColor]];
        [self.contentView addSubview:nameLbl];

        notificationLbl = [[UILabel alloc]init];
        [notificationLbl setTextColor:[UIColor lightGrayColor]];
        notificationLbl.translatesAutoresizingMaskIntoConstraints = NO;
        [notificationLbl setTextAlignment:NSTextAlignmentLeft];
        [notificationLbl setNumberOfLines:1];
        [self.contentView addSubview:notificationLbl];

        textLabel = [[UILabel alloc]init];
        [textLabel setTextColor:[UIColor blueColor]];
        textLabel.translatesAutoresizingMaskIntoConstraints = NO;
        [textLabel setTextAlignment:NSTextAlignmentLeft];
        [textLabel setNumberOfLines:0];
        [textLabel setBackgroundColor:[UIColor grayColor]];
        [self.contentView addSubview:textLabel];

        timeLbl = [[UILabel alloc]init];
        [timeLbl setTextColor:[UIColor grayColor]];
        timeLbl.translatesAutoresizingMaskIntoConstraints = NO;
        [timeLbl setTextAlignment:NSTextAlignmentLeft];
        [timeLbl setNumberOfLines:1];

        [self.contentView addSubview:timeLbl];

        profileImgView = [[UIImageView alloc]init];
        [profileImgView setTranslatesAutoresizingMaskIntoConstraints:NO];
        [profileImgView setBackgroundColor:[UIColor redColor]];
        [profileImgView.layer setCornerRadius:20];
        [profileImgView.layer setMasksToBounds:YES];
        [self.contentView addSubview:profileImgView];

        clockImgView = [[UIImageView alloc]init];
        [clockImgView setTranslatesAutoresizingMaskIntoConstraints:NO];
        [clockImgView setBackgroundColor:[UIColor blueColor]];
        [clockImgView.layer setCornerRadius:10];
        [clockImgView.layer setMasksToBounds:YES];
        [self.contentView addSubview:clockImgView];

        notificationImgView = [[UIImageView alloc]init];
        [notificationImgView setTranslatesAutoresizingMaskIntoConstraints:NO];
        [notificationImgView setBackgroundColor:[UIColor purpleColor]];
        [notificationImgView.layer setCornerRadius:10];
        [notificationImgView.layer setMasksToBounds:YES];
        [self.contentView addSubview:notificationImgView];

        /*[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[_headerView(==80)]-0-[_tableView]-|"
                                                                          options:NSLayoutFormatDirectionLeadingToTrailing
                                                                          metrics:nil
                                                                            views:elementsDict]];*/



    }
    return self;
}
-(void)updateConstraints{
    if (self.didSetupConstraints == NO) {

        NSDictionary *views = NSDictionaryOfVariableBindings(nameLbl,notificationLbl,notificationImgView,textLabel,timeLbl,profileImgView,clockImgView);
        NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[profileImgView(40)]-10-[textLabel]-[clockImgView(20)]-[timeLbl(20)]-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:views];
        [self.contentView addConstraints:constraints];

        constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:[profileImgView]-10-[nameLbl]-[clockImgView]" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:views];
        [self.contentView addConstraints:constraints];

        constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:[profileImgView]-10-[notificationImgView(20)]-[notificationLbl]-[clockImgView]" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:views];
        [self.contentView addConstraints:constraints];

        constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[nameLbl]-[notificationLbl]-[textLabel]-20-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:views];
        [self.contentView addConstraints:constraints];

        constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[notificationImgView(20)]-[textLabel]" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:views];
        [self.contentView addConstraints:constraints];

        constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-15-[profileImgView(40)]" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:views];
        [self.contentView addConstraints:constraints];

        constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-15-[clockImgView(20)]" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:views];
        [self.contentView addConstraints:constraints];

        constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-15-[timeLbl]" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:views];
        [self.contentView addConstraints:constraints];
        self.didSetupConstraints = YES;
    }
    [super updateConstraints];
}
- (void)layoutSubviews
{
    [super layoutSubviews];

    [self.contentView setNeedsLayout];
    [self.contentView layoutIfNeeded];

    self.textLabel.preferredMaxLayoutWidth = CGRectGetWidth(self.textLabel.frame);
}
4

4 回答 4

1

几个想法:

  1. 确保您既没有rowHeight在表格视图上显式设置属性,也没有tableView:heightForRowAtIndexPath:UITableViewDelegate. 其中任何一个都会与执行基于约束的高度计算的单元建立冲突的约束。

  2. 虽然我认为没有必要,但“Luke 说”(在 WWDC 2014 视频What's New in Table and Collection Views中)在使用约束生成的行高时应该estimatedRowHeight为表视图(例如 in )设置。viewDidLoad

    self.tableView.estimatedRowHeight = 44;
    
  3. 我也没有发现有必要这样做,但是在同一个 WWDC 2014 视频中,演示者 Luke 遇到了与您类似的奇怪约束错误,直到他在他的代码中添加了以下行:

    self.tableView.rowHeight = UITableViewAutomaticDimension;
    

    他说这在下一粒种子中是没有必要的,但在他的示范中,这是必要的。

  4. 我注意到您仍然经常会收到不可满足的约束错误(即使您已经完成了上述操作并且所有约束都很好)。我发现,如果您将单元格的垂直约束之一更改为优先级小于 1000,则似乎可以解决此问题(并且单元格的格式似乎正确。

请注意,这种自动计算行高的行为在 iOS 7 中有所不同。但在 iOS 8 中,上面应该这样做。如果您仍然遇到问题,请创建一个显示问题的测试项目并将其上传到我们可以查看的地方。

于 2015-03-08T04:59:39.120 回答
0

我对动态单元高度的一些建议:

首先,不要覆盖updateConstraints. NotificationCellinit将所有子视图添加到contentView.

然后,改变你的实现heightForRow

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *) indexPath {
        NotificationCell *cell = [[NotificationCell alloc] init];

        // Do all your configuration here 
        cell.nameLabel.text = [_names objectAtIndex:indexPath.row];
        // Add all the rest too ... 

        CGFloat cellHeight = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingSizeCompressedSize].height;
        // Add a breakpoint here to see if your constraints are right and if the height is calculated correctly

        return height + 1;
}

如果您的标签不是多行的,即使没有设置文本,也应该正确计算高度。但是,如果它们可以跨越多行,那么您需要在heightForRow方法中设置文本的值。

希望这可以解决您的问题。

于 2015-03-17T18:08:41.237 回答
0

发生这种情况是因为您的单元格的高度是 44 点,但是您有垂直放置的标签,其中只有空格是 20 + 标准间距 + 标准间距 + 20 肯定大于 44,并且仍然有标签高度,您必须考虑到:V:|-20-[nameLbl]-[notificationLbl]-[textLabel]-20-|。所以你应该增加你的细胞的高度。

于 2015-03-07T16:20:43.450 回答
0

你需要设置self.tableView.rowHeight = UITableViewAutomaticDimension; 它将动态地使 tableViewCell 高度。

您可能还需要将高度约束设置为大于等于相同的标签,以便如果不是内容,它的高度可以为 0。

于 2015-03-17T05:15:07.383 回答