自动布局约束抛出异常

问题描述 投票:0回答:1

我正在对要加载到表格视图单元格的字段使用自动布局。对于每个单元格,我从contentView中清除所有子视图,并根据需要的字段类型加载自己的视图。大多数单元格都很好,但是当这个单元格出现时,我得到一个例外。

这里是单元格的代码:

UILabel *questionText = [[UILabel alloc] init];
questionText.text = self.field.questionText;
questionText.font = font;
questionText.numberOfLines = 0;
questionText.adjustsFontSizeToFitWidth = NO;
questionText.lineBreakMode = NSLineBreakByWordWrapping;
[questionText setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.contentView addSubview:questionText];

UIView *listContainer = [[UIView alloc] init];
listContainer.backgroundColor = [UIColor whiteColor];
listContainer.layer.cornerRadius = 8;
listContainer.layer.borderWidth = 1.0;
[listContainer setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.contentView addSubview:listContainer];

// Get the views dictionary
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(questionText, listContainer);

//Create the constraints using the visual language format
NSString *format = @"V:|-10-[questionText]-10-[listContainer]-10-|";
NSArray *constraintsArray = [NSLayoutConstraint constraintsWithVisualFormat:format options:NSLayoutFormatAlignAllLeft metrics:nil views:viewsDictionary];
[self.contentView addConstraints:constraintsArray];

format = @"|-10-[questionText]-10-|";
constraintsArray = [NSLayoutConstraint constraintsWithVisualFormat:format options:NSLayoutFormatAlignAllLeft metrics:nil views:viewsDictionary];
[self.contentView addConstraints:constraintsArray];

format = @"|-10-[listContainer]-10-|";
constraintsArray = [NSLayoutConstraint constraintsWithVisualFormat:format options:NSLayoutFormatAlignAllLeft metrics:nil views:viewsDictionary];
[self.contentView addConstraints:constraintsArray];


ToggleButton *prevCheckbox;
ToggleButton *checkbox;

for (AssessmentAnswer *answer in self.field.answers)
{
    checkbox = [[ToggleButton alloc] initWithText:answer.text ofType:ToggleButtonTypeCheckbox];
    [checkbox setTranslatesAutoresizingMaskIntoConstraints:NO];
    [listContainer addSubview:checkbox];


    viewsDictionary = NSDictionaryOfVariableBindings(checkbox);
    format = @"|-10-[checkbox]-10-|";
    constraintsArray = [NSLayoutConstraint constraintsWithVisualFormat:format options:NSLayoutFormatAlignAllCenterY metrics:nil views:viewsDictionary];
    [listContainer addConstraints:constraintsArray];

    if (prevCheckbox)
    {
        // This is not the first item
        [listContainer addConstraint:[NSLayoutConstraint constraintWithItem:checkbox attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:prevCheckbox attribute:NSLayoutAttributeBottom multiplier:1.0 constant:20.0]];
    }
    else
    {
        // This is the first item
        [listContainer addConstraint:[NSLayoutConstraint constraintWithItem:checkbox attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:listContainer attribute:NSLayoutAttributeTop multiplier:1.0 constant:10.0]];
    }

    prevCheckbox = checkbox;
}

if (checkbox)
{
    // This is the last checkbox
    [listContainer addConstraint:[NSLayoutConstraint constraintWithItem:listContainer attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:checkbox attribute:NSLayoutAttributeBottom multiplier:1.0 constant:10.0]];
}

在这种情况下,self.field.answers中只有一项。字体与下面使用的值相同。

这里是单元格高度的代码:

UIFont *font = [UIFont fontWithName:@"Helvetica" size:14.0];

//Find height of question text
CGFloat questionTextHeight = [field.questionText sizeWithFont:font constrainedToSize:CGSizeMake(width - (2 * PAD_X), CGFLOAT_MAX) lineBreakMode:NSLineBreakByWordWrapping].height;

//Find height of each row
CGFloat listHeight = 0.0;

for (AssessmentAnswer *answer in field.answers)
{
    listHeight += MAX([answer.text sizeWithFont:font constrainedToSize:CGSizeMake(width - 43.0 - [ToggleButton getImageWidth], CGFLOAT_MAX) lineBreakMode:NSLineBreakByWordWrapping].height, [ToggleButton getImageHeight]) + 20.0;
}

// Question text height + list height + spacers
return questionTextHeight + listHeight + 30.0;

这里是创建ToggleButton(即UIButton :)的内部的代码:

for (UIView *subview in self.subviews)
{
    [subview removeFromSuperview];
}

// Add the toggle button image
self.toggleImgView = [[UIImageView alloc] init];
[self.toggleImgView setTranslatesAutoresizingMaskIntoConstraints:NO];
[self addSubview:self.toggleImgView];

// Add the label
self.toggleLabel = [[UILabel alloc] init];
self.toggleLabel.font = [UIFont fontWithName:@"Helvetica" size:14.0f];
self.toggleLabel.numberOfLines = 0;
self.toggleLabel.adjustsFontSizeToFitWidth = NO;
self.toggleLabel.lineBreakMode = NSLineBreakByWordWrapping;
self.toggleLabel.backgroundColor = [UIColor clearColor];
[self.toggleLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
[self addSubview:self.toggleLabel];

// Get the views dictionary
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(_toggleImgView, _toggleLabel);

//Create the constraints using the visual language format
NSString *format = [NSString stringWithFormat:@"|-0-[_toggleImgView(%f)]-3-[_toggleLabel]-0-|", IMAGE_WIDTH];
NSArray *constraintsArray = [NSLayoutConstraint constraintsWithVisualFormat:format options:nil metrics:nil views:viewsDictionary];
[self addConstraints:constraintsArray];

viewsDictionary = NSDictionaryOfVariableBindings(_toggleLabel);
format = [NSString stringWithFormat:@"V:|-0-[_toggleLabel(>=%f)]-0-|", IMAGE_HEIGHT];
constraintsArray = [NSLayoutConstraint constraintsWithVisualFormat:format options:NSLayoutFormatAlignAllLeft metrics:nil views:viewsDictionary];
[self addConstraints:constraintsArray];


[self addConstraint:[NSLayoutConstraint constraintWithItem:self.toggleImgView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.toggleImgView attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0.0]];

[self addConstraint:[NSLayoutConstraint constraintWithItem:self.toggleImgView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.toggleLabel attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0.0]];

这是我得到的异常读数:

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:0x1f28c4f0 V:[UILabel:0x1f288f10(>=27)]>",
    "<NSLayoutConstraint:0x1f291460 V:[ToggleButton:0x1f068e50]-(10)-|   (Names: '|':UIView:0x1f0182a0 )>",
    "<NSLayoutConstraint:0x1f293830 V:[UILabel:0x1f288f10]-(0)-|   (Names: '|':ToggleButton:0x1f068e50 )>",
    "<NSLayoutConstraint:0x1f28b480 V:|-(10)-[UILabel:0x1f062890]   (Names: '|':UITableViewCellContentView:0x1f1c23d0 )>",
    "<NSLayoutConstraint:0x1f29b070 V:|-(10)-[ToggleButton:0x1f068e50]   (Names: '|':UIView:0x1f0182a0 )>",
    "<NSLayoutConstraint:0x1f289810 V:[UIView:0x1f0182a0]-(10)-|   (Names: '|':UITableViewCellContentView:0x1f1c23d0 )>",
    "<NSLayoutConstraint:0x1f292eb0 V:|-(0)-[UILabel:0x1f288f10]   (Names: '|':ToggleButton:0x1f068e50 )>",
    "<NSLayoutConstraint:0x1f28dc90 V:[UILabel:0x1f062890]-(10)-[UIView:0x1f0182a0]>",
    "<NSAutoresizingMaskLayoutConstraint:0x1f1e5ed0 h=--& v=--& V:[UITableViewCellContentView:0x1f1c23d0(60)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x1f293830 V:[UILabel:0x1f288f10]-(0)-|   (Names: '|':ToggleButton:0x1f068e50 )>

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.

我不明白为什么我会得到例外,因为所有的身高加起来。其他一些单元格类型也正在发生这种情况,因此任何见解都会有所帮助。

objective-c exception constraints autolayout nslayoutconstraint
1个回答
1
投票

错误消息告诉您,它不能满足要求ToggleButton内的UILabel的高度大于或等于27的约束。大概在布局过程中的某个时候,没有空间可以这样做,同时保留您已设置的其他垂直间距规则。

有趣的是,我实际上没有参见有关UILabel的高度在您的代码中的约束;也许您将其设置在笔尖中?如果是这样,请尝试降低其优先级,或者也许在其上装入一个插座并在笔尖装入后将其卸下。从这里开始有点神秘,因为您没有解释什么是ToggleButton。但是它里面似乎确实有一个UILabel,并且UILabel似乎确实有一个高度不平等,这是造成问题的原因。

© www.soinside.com 2019 - 2024. All rights reserved.