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