Как программно добавить ограничение в объект c

Я хочу добавить ограничение программно и использую приведенный ниже код для добавления ограничения TOP и LEFT.

NSLayoutConstraint *top = [NSLayoutConstraint constraintWithItem:label1
                                                       attribute:NSLayoutAttributeTop
                                                       relatedBy:NSLayoutRelationEqual
                                                          toItem:self.view
                                                       attribute:NSLayoutAttributeTop
                                                      multiplier:1
                                                        constant:110];


NSLayoutConstraint *left = [NSLayoutConstraint constraintWithItem:label1
                                                        attribute:NSLayoutAttributeLeading
                                                        relatedBy:NSLayoutRelationEqual
                                                           toItem:self.view
                                                        attribute:NSLayoutAttributeLeading
                                                       multiplier:1
                                                         constant:10];

lable1 добавлен в мой контроллер представления. Когда я добавляю эти два ограничения в представление вроде

[self.view addConstraint:top];
[self.view addConstraint:left];

Это дает ошибку в консоле, а ограничение не влияет на ярлык.

2016-02-09 19:36:59.824 testinMRC[99160:313382] 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. 
(
    "<NSLayoutConstraint:0x7fa5c8738610 V:|-(110)-[UILabel:0x7fa5c8626940'Label']   (Names: '|':UIView:0x7fa5c86267b0 )>",
    "<NSIBPrototypingLayoutConstraint:0x7fa5c8628a70 'IB auto generated at build time for view with fixed frame' V:|-(88)-[UILabel:0x7fa5c8626940'Label']   (Names: '|':UIView:0x7fa5c86267b0 )>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x7fa5c8738610 V:|-(110)-[UILabel:0x7fa5c8626940'Label']   (Names: '|':UIView:0x7fa5c86267b0 )>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
2016-02-09 19:36:59.889 testinMRC[99160:313382] 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. 
(
    "<NSLayoutConstraint:0x7fa5c87334b0 H:|-(10)-[UILabel:0x7fa5c8626940'Label']   (Names: '|':UIView:0x7fa5c86267b0 )>",
    "<NSIBPrototypingLayoutConstraint:0x7fa5c86285c0 'IB auto generated at build time for view with fixed frame' H:|-(188)-[UILabel:0x7fa5c8626940'Label'](LTR)   (Names: '|':UIView:0x7fa5c86267b0 )>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x7fa5c87334b0 H:|-(10)-[UILabel:0x7fa5c8626940'Label']   (Names: '|':UIView:0x7fa5c86267b0 )>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

Может ли кто-нибудь сказать мне, почему возникла эта ошибка? Помогите мне найти решение


person Crazy Developer    schedule 09.02.2016    source источник
comment
используйте кладку для программного добавления ограничений.   -  person Teja Nandamuri    schedule 10.02.2016
comment
Последний способ добавлен сюда: stackoverflow.com/a/51531647/4061501   -  person Lal Krishna    schedule 26.07.2018


Ответы (3)


В вашем случае ошибка четко указывает, что у вас есть конфликтующие ограничения для вашего представления. Вероятно, потому что вы пытаетесь добавить ограничения к представлению, которое уже есть в Интерфейсном Разработчике. Даже если вы не установили какие-либо ограничения явно, IB предоставляет их вам, когда обнаруживает, что некоторые из них отсутствуют.

Я вижу в комментариях, о которых вы упомянули, что вы хотите делать все программно. В этом случае взгляните на кусок кода:

- (void)viewDidLoad {
    [super viewDidLoad];

    UIView *view = [UIView new];
    view.backgroundColor = [UIColor redColor];

    [view setTranslatesAutoresizingMaskIntoConstraints:NO];

    [self.view addSubview:view];

    NSLayoutConstraint *left = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1 constant:100];
    NSLayoutConstraint *top = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1 constant:100];

    NSLayoutConstraint *height = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:50];
    NSLayoutConstraint *width = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:50];

    [self.view addConstraints:@[left, top]];
    [view addConstraints:@[height, width]];

}

Это довольно понятно. Как видите, мне пришлось добавить ограничения по ширине и высоте для представления, потому что только left и top не полностью описывают его положение.

Результат:

введите описание изображения здесь

Я рекомендую вам попробовать язык визуального формата. Тот же результат может быть достигнут с гораздо меньшим количеством кода. Этот код приводит к тому же результату:

NSArray *horizontal = [NSLayoutConstraint constraintsWithVisualFormat:@"|-100-[view(50)]" options:0 metrics:nil views:@{@"view" : view}];
NSArray *vertical = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-100-[view(50)]" options:0 metrics:nil views:@{@"view" : view}];

[self.view addConstraints:vertical];
[self.view addConstraints:horizontal];

Сообщите мне, помогло ли это. Ваше здоровье.

person NKorotkov    schedule 10.02.2016
comment
[view setTranslatesAutoresizingMaskIntoConstraints:NO]; Это ключевое требование. - person Ahmed Khalaf; 28.02.2017

Проблема не в вашем коде, а в сообщении IB auto generated at build time for view with fixed frame:

Интерфейсный разработчик автоматически генерирует ограничения для вас, если вы не добавляете их самостоятельно. Вы можете избежать этого либо

  • Выберите перо или раскадровку в Project Navigator, перейдите в File Inspector и снимите флажок Use Auto Layout.

or

  • Добавьте некоторые ограничения в Интерфейсном Разработчике и установите их на remove at build time.
person Jörn Buitink    schedule 09.02.2016
comment
Первый вариант, снятие флажка Use Auto Layout, вероятно, окажет огромное влияние на проект и потребует, чтобы OP переключился на изменение размера старых стоек и пружин. Ваш второй вариант добавления недостающих ограничений и пометки их как удаленных во время сборки кажется гораздо лучшим решением. - person Duncan C; 09.02.2016
comment
Я хочу создать время выполнения ярлыка. является ли этот приведенный выше код правильным, когда метка создается во время выполнения. - person Crazy Developer; 09.02.2016

Похоже, у вас конфликтующие ограничения макета. Ограничение, скорее всего, было настроено в раскадровке, и вы пытаетесь программно добавить ограничение, которое напрямую конфликтует с ним.

Похоже, вы пытаетесь убрать UIView с дороги после того, как произошло действие. Т.е. нажмите кнопку и переместите изображение счастливого лица из середины экрана в верхний левый угол.

Добавление и удаление ограничений непосредственно в коде может быть ОГРОМНОЙ головной болью из-за раздувания кода, модульного тестирования и предупреждений, заполняющих вашу консоль.

Возможно, было бы лучше создать основной UIView в раскадровке и иметь скрытый заполнитель UIView, который содержит все ограничения, которые вы хотите, чтобы UIView имел после нажатия кнопки. Затем вы можете программно отключить все ограничения для этих UIView. Таким образом, вид, который вы хотите изменить, будет иметь положение, ширину и высоту заполнителя, а заполнитель будет иметь положение и высоту представления, которое вы хотите изменить.

Таким образом, у вас никогда не будет этой ошибки при программном изменении ограничений макета, потому что любые ошибки будут обнаружены раскадровкой.

Есть открытый исходный код, который делает это за вас одной или двумя строчками кода. (В документации также есть несколько видеоуроков по YouTube) https://cocoapods.org/pods/SBP

После установки cocoapod ваш код будет выглядеть примерно так

это будет код внутри контроллера представления с UIView, который вы хотите изменить, и заполнителем UIView

//UIView* viewBeforeChange
//UIView* hiddenViewAfterChange
[self switchViewConst:viewBeforeChange secondView:hiddenViewAfterChange];
person Arjay Waran    schedule 10.02.2016