it-swarm.com.ru

Как программно добавить ограничение в цель 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.

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

5
Crazy Developer

В вашем случае ошибка ясно указывает на наличие противоречивых ограничений для вашего взгляда. Возможно, потому что вы пытаетесь добавить ограничения к представлению, которое уже имеет некоторые из Interface Builder. Даже если вы не установили никаких ограничений явно, 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 не полностью описывают его положение.

Результат:

 enter image description here

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

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

Дайте мне знать, если это помогло. Приветствия.

9
NKorotkov

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

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

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

или же

  • Добавьте некоторые ограничения в Интерфейсный Разработчик и установите для них remove at build time.
1
Jörn Buitink

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

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

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

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

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

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

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

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

//UIView* viewBeforeChange
//UIView* hiddenViewAfterChange
[self switchViewConst:viewBeforeChange secondView:hiddenViewAfterChange];
0
Arjay Waran