AutoLayout, не может одновременно удовлетворять ограничениям
Просто начал изучать iOS AutoLayout, построитель интерфейса очень прямо, но когда я пытаюсь архивировать то же самое на коде
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(==2)-[_nextKeyboardButton]-(==2)-[_numPadButton]-(==2)-[_spaceButton]-(==2)-[_returnButton]-(==2)-|" options:0 metrics:0 views:NSDictionaryOfVariableBindings(_nextKeyboardButton,_numPadButton,_spaceButton,_returnButton)]];
возникает исключение,
Невозможно одновременно удовлетворить ограничениям.
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:0x6000000966c0 H:|-(2)-[UIButton:0x7fe4f1d1c760'Next'] (Names: '|':UIInputView:0x7fe4f1f04d00 )>",
"<NSLayoutConstraint:0x600000096710 H:[UIButton:0x7fe4f1d1c760'Next']-(2)-[UIButton:0x7fe4f1d1d1d0'123']>",
"<NSLayoutConstraint:0x600000096760 H:[UIButton:0x7fe4f1d1d1d0'123']-(2)-[UIButton:0x7fe4f1d1d6f0'Space']>",
"<NSLayoutConstraint:0x6000000967b0 H:[UIButton:0x7fe4f1d1d6f0'Space']-(2)-[UIButton:0x7fe4f1d1d8d0'Return']>",
"<NSLayoutConstraint:0x600000096800 H:[UIButton:0x7fe4f1d1d8d0'Return']-(2)-| (Names: '|':UIInputView:0x7fe4f1f04d00 )>",
"<NSLayoutConstraint:0x600000096e40 'UIView-Encapsulated-Layout-Width' H:[UIInputView:0x7fe4f1f04d00(0)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x6000000967b0 H:[UIButton:0x7fe4f1d1d6f0'Space']-(2)-[UIButton:0x7fe4f1d1d8d0'Return']>
Все 4 кнопки .translatesAutoresizingMaskIntoConstraints = NO;
Интересно, что не так? помощь действительно оценена:)
FYI: Я работаю над SDK iOS8
Ответы
Ответ 1
Самый простой способ найти неудовлетворительные ограничения:
- установить уникальный идентификатор для каждого ограничения в вашем представлении:
![введите описание изображения здесь]()
- создать простое расширение для
NSLayoutConstraint
:
SWIFT:
extension NSLayoutConstraint {
override public var description: String {
let id = identifier ?? ""
return "id: \(id), constant: \(constant)" //you may print whatever you want here
}
}
OBJECTIVE-C
@interface NSLayoutConstraint (Description)
@end
@implementation NSLayoutConstraint (Description)
-(NSString *)description {
return [NSString stringWithFormat:@"id: %@, constant: %f", self.identifier, self.constant];
}
@end
- постройте его еще раз, и теперь у вас есть более читаемый вывод для вас:
![введите описание изображения здесь]()
- После того, как вы получили свой
id
, вы можете просто коснуться его в Навигаторе поиска:
![введите описание изображения здесь]()
![введите описание изображения здесь]()
КАК ПРОСТО УСТАТЬ СЛУЧАЙ?
- попробуйте изменить приоритет на
999
для сломанного ограничения.
См. соответствующий ответ здесь: Невозможно одновременно удовлетворить ограничения, попытается восстановить, нарушив ограничение
Ответ 2
Мне пришлось бороться с подобной проблемой, когда я пытался вручную создать все ограничения автоматического макета (в Swift, используя Snappy - порт масонства для Swift) в контроллере представления, который основан на раскадровке.
По какой-то причине Xcode генерирует собственный набор ограничений автоматического макета по умолчанию для NIB во время сборки. Вот почему я не мог добавить никаких дополнительных ограничений вручную, потому что они противоречили автоматически добавленным.
Я решил это следующим образом:
-
Откройте диспетчер просмотра раскадровки, который вы обрабатываете.
-
Выберите контроллер просмотра и выберите Редактоp > Решение проблем автоматического макетa > Все представления в [] Просмотр контроллерa > Добавить отсутствующие ограничения из меню:
![enter image description here]()
(Это гарантирует, что не создаются дополнительные ограничения времени сборки и все ограничения теперь видны.)
- Выберите все ограничения с вашего контроллера:
![enter image description here]()
- Отметьте из правой панели следующий флажок: Заполнитель - Удалить во время сборки:
![enter image description here]()
Теперь вы можете добавить все ограничения автоматической компоновки вручную в код.
Ответ 3
Это может быть не так сложно. На выходе консоли сообщений указано, что ограничения UIButton переопределены. Это означает, что вы просто устанавливаете ограничение, ограничивающее Height
и Width
кнопки, но, разумеется, вы ставите другой ограничение на то, что кнопка имеет Aspect Ratio
. В этом условии Xcode не может убедиться в том, какое ограничение следует выполнить, чтобы вы могли видеть это сообщение отладки в консоли.
Есть два способа для меня:
- Проанализируйте ограничения, отображаемые в консоли, и попытайтесь удалить одно или несколько ограничений.
2.Если вы используете storyboard
или Xib
, выберите ограничение → Показать инспектор атрибутов → измените приоритет некоторых ограничений.
Еще одна вещь...
Вы можете следовать статье статьи Джейсона Джарретта. Добавьте контрольную точку символа, чтобы убедиться, что вид ошибки вызывает ошибку.
Ответ 4
В соответствии с вашим вопросом, что я понял, что вы создали элемент управления в nib, и вы прямо пытаетесь изменить ограничения вашего класса.
Здесь вы можете установить ограничения в nib для контроллера представления, а затем привязать его к вашему классу и использовать объекты ограничений. Или вы можете создавать представление программно и напрямую устанавливать ограничения.
//Вам также нужно проверить, нужно ли вам переводитьAutoresizingMaskIntoConstraints, если "YES" - просмотр представлений рассматривает маску авторазрешения, создает ограничения, которые ее реализуют, и добавляет эти ограничения к себе (супервизор) ". и если" НЕТ - супервизор представлений не смотрит на маску авторезистирования, а не создает ограничения, которые ее реализуют".
У меня тоже была проблема, и я исправил ее как
[_nextKeyboardButton setTranslatesAutoresizingMaskIntoConstraints:YES];
_numPadButton.translatesAutoresizingMaskIntoConstraints = YES;
[_numPadButton updateConstraints];
[_nextKeyboardButton updateConstraints];
NSArray *constraints2 = [NSLayoutConstraint
constraintsWithVisualFormat:@"H:|-57-[_nextKeyboardButton(96)]"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(_nextKeyboardButton)];
[self.view addConstraints:constraints2];
NSArray *constraints4 = [NSLayoutConstraint
constraintsWithVisualFormat:@"V:|-123-[_nextKeyboardButton(30)]"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(_nextKeyboardButton)];
[self.view addConstraints:constraints4];
NSArray *constraints1 = [NSLayoutConstraint
constraintsWithVisualFormat:@"H:|-207-[_numPadButton(58)]"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(_numPadButton)];
[self.view addConstraints:constraints1];
NSArray *constraints3 = [NSLayoutConstraint
constraintsWithVisualFormat:@"V:|-123-[_numPadButton(30)]"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(_numPadButton)];
[self.view addConstraints:constraints3];
// Create Controls or view programmatically.
UILabel *label = [UILabel new];
label.text = @"This is a Label";
label.font = [UIFont systemFontOfSize:18];
label.backgroundColor = [UIColor lightGrayColor];
label.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:label];
NSArray *constraints = [NSLayoutConstraint
constraintsWithVisualFormat:@"V:|-offsetTop-[label(100)]"
options:0
metrics:@{@"offsetTop": @100}
views:NSDictionaryOfVariableBindings(label)];
[self.view addConstraints:constraints];
UIView *spacer1 = [UIView new];
spacer1.translatesAutoresizingMaskIntoConstraints = NO;
[spacer1 setBackgroundColor:[UIColor redColor]];
[self.view addSubview:spacer1];
UIView *spacer2 = [UIView new];
spacer2.translatesAutoresizingMaskIntoConstraints = NO;
[spacer2 setBackgroundColor:[UIColor greenColor]];
[self.view addSubview:spacer2];
NSArray *constraints1 = [NSLayoutConstraint
constraintsWithVisualFormat:@"V:|-offsetTop-[spacer1(100)]"
options:0
metrics:@{@"offsetTop": @100}
views:NSDictionaryOfVariableBindings(spacer1)];
[self.view addConstraints:constraints1];
NSArray *constraints2 = [NSLayoutConstraint
constraintsWithVisualFormat:@"V:|-offsetTop-[spacer2(100)]"
options:0
metrics:@{@"offsetTop": @100}
views:NSDictionaryOfVariableBindings(spacer2)];
[self.view addConstraints:constraints2];
[self.view addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:@"H:|[spacer1]-10-[label]-20-[spacer2(==spacer1)]|"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(label, spacer1, spacer2)]];
Поэтому при использовании AutoLayout вы никогда не должны напрямую устанавливать рамку представления. Для этого используются ограничения. Обычно, если вы хотите установить свои собственные ограничения в представлении, вы должны переопределить метод updateConstraints вашего UIViews. Убедитесь, что просмотры содержимого для контроллера страниц позволяют изменять их края, поскольку они будут иметь размер, соответствующий размеру окна просмотра страницы. Ваши ограничения и настройка просмотра должны будут учитывать это, или вы получите неудовлетворительные ошибки ограничения.
https://developer.apple.com/library/mac/documentation/userexperience/conceptual/AutolayoutPG/AutoLayoutConcepts/AutoLayoutConcepts.html#//apple_ref/doc/uid/TP40010853-CH14-SW1
Вы также можете ссылаться на ссылку яблока на углубленное исследование, и если вы все еще сталкиваетесь с проблемой, постарайтесь, чтобы мой уровень лучше всего разрешал вам проблему.
Ответ 5
В случае, если кто-то еще сталкивается с этим, простой способ визуально проверить проблемы с вашими ограничениями - это сайт (это действительно полезно!):
http://www.wtfautolayout.com
Здесь проект Github в случае, если сайт опускается:
https://github.com/johnpatrickmorgan/wtfautolayout