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]]; 

Вот исключение считывания I я получаю:

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. 

Я не понимаю, почему я получаю исключение, потому что все высоты складываются , Этот сценарий происходит с несколькими другими типами ячеек, поэтому любое понимание было бы полезно.

ответ

1

Сообщение об ошибке сообщает вам совершенно ясно, что оно не может удовлетворить ограничение, требующее, чтобы UILabel внутри ToggleButton был больше или равным 27 по высоте. Предположительно, в какой-то момент во время макета нет места для этого, сохраняя другие правила вертикального расстояния, которые вы установили.

Интересно, что я действительно не см. ограничение относительно высоты UILabel в вашем коде; возможно, вы устанавливаете это в банке? Если это так, попробуйте уменьшить его приоритет или, возможно, настройте выход на него и удалите его после нагрузок. Это немного мистифицирует отсюда, потому что вы не объясняете, что такое ToggleButton. Но в нем определенно есть UILabel, и у UILabel определенно есть неравенство в высоте, которое является причиной проблемы.

+0

Да, я понимаю, что сообщение об ошибке сообщает мне. Я не знаю, почему ограничение конфликтует с другим. Я добавляю код внутри ToggleButton, так как именно там находится UILabel. – Alex311

+1

Хорошо, но вместо того, чтобы трещать, попробуйте то, что я советую вам попробовать: добавьте пониженный приоритет этому ограничению неравенства на высоту '_toggleLabel'. Просто опустите его на одну точку (до 999). Затем запустите приложение и посмотрите, что произойдет. – matt