Есть ли способ добавить идентификатор в Auto Layout Constraints в Interface Builder?

После выполнения некоторой визуальной компоновки в Interface Builder я создал некоторые ограничения, к которым я хочу получить доступ во время выполнения. Есть ли способ маркировать или идентифицировать ограничения в Interface Builder, чтобы их можно было просмотреть позже?

Причина, по которой я хочу это сделать, - мне нужно выполнить некоторую базу вычислений на визуально определенных ограничениях. Я знаю, что Apple предоставила Язык Visual Format, и я мог бы указать ограничения программным образом в контроллере. Я предпочитаю не использовать этот подход, поэтому я не теряю обратную связь времени разработки IB.

Изменить

Создание ссылочной розетки действительно сработало, но вопрос все еще стоит.

Ответ 1

Update:

Как объяснил Bartłomiej Semańczyk в его ответе, теперь в Inspector Attributes для NSLayoutConstraint отображается поле Идентификатор не нужно выставлять это поле самостоятельно. Просто выберите ограничение в представлении "Структура документа" или в представлении "Раскадровка", а затем добавьте идентификатор в Инспекторе атрибутов справа.


Ранее ответ:

Да, это можно сделать. NSLayoutConstraint имеет свойство identifier, которое может быть выставлено в Interface Builder и назначено. Чтобы продемонстрировать это, я создал приложение Single View, у которого есть одно подзаголовок, который является красным полем. В этом представлении есть 4 ограничения: ширина, высота, по горизонтали в контейнере, вертикально в контейнере. Я дал ограничение ширины идентификатора redBoxWidth, выполнив следующее:

  • Нажмите на ограничение ширины в представлении макета документа. Затем в Инспекторе идентификации в разделе Атрибуты времени выполнения, определенные пользователем, нажмите + в разделе Путь к ключу. Измените keyPath на идентификатор, измените Тип Boolean на String и установите Значение на redBoxWidth.

    naming a constraint

  • Затем в ViewDidLoad можно найти ограничение по имени и изменить его значение:

    class ViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            for subview in view.subviews as [UIView] {
                for constraint in subview.constraints() as [NSLayoutConstraint] {
                    if constraint.identifier == "redBoxWidth" {
                        constraint.constant = 300
                    }
                }
            }
        }
    }
    

Ответ 2

  • С Xcode 7 вы можете сделать это в раскадровке:

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

  1. Однако, если вы настроите свое ограничение в коде, сделайте следующее:

    let constraint = NSLayoutConstraint() 
    constraint.identifier = "identifier"
    
  2. Для этих ограничений, которые вы настроили в раскадровке, но вы должны установить идентификатор в коде:

    for subview in view.subviews {
        for constraint in subview.constraints() {
            constraint.identifier = "identifier"
        }
    }
    

Ответ 3

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

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

И тогда он будет доступен в коде вашего контроллера как свойство:

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *myConstraint;

И вы можете изменить его значение, например:

self.myConstraint.constant=100.;

Ответ 4

Просто добавьте ответ на @vacawama. Вы можете написать категорию UIView и вытащить ограничения, используя простую функцию, в отличие от копирования/вставки циклов везде, где вам нужно найти ограничение:

.h файл:

#import <UIKit/UIKit.h>

@interface UIView (EasyAutolayout)

-(NSLayoutConstraint *)constraintForIdentifier:(NSString *)identifier;

@end

.m file:

#import "UIView+EasyAutolayout.h"

@implementation UIView (EasyAutolayout)

-(NSLayoutConstraint *)constraintForIdentifier:(NSString *)identifier {

    for (NSLayoutConstraint *constraint in self.constraints) {
        if ([constraint.identifier isEqualToString:identifier]) {
            return constraint;
        }
    }
    return nil;
}

@end

Ответ 5

Возьмите IBOutlet вашего ограничения автоматической компоновки.

В классе NSLayoutConstraint есть одно свойство с именем константа.

Например, вы взяли IBOutlet ограничения высоты любого из видов из вашего IB и хотите программно изменить его высоту, все, что вам нужно сделать, это:

 constraint.constant = isMoreHeight ? height1 : height2;

После этого вам нужно обновить все другие представления в иерархии представлений супервизора. Для этого вам нужно написать следующую строку:

[self setLayoutIfNeeded];

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

[UIView animateWithDuration:0.3f animations:^{
      [self.view layoutIfNeeded];
}];

Надеюсь, что это поможет.

Ответ 6

Как насчет этого:

if let myconstraint = self.view.constraints.filter( { $0.identifier == "myconstraintId" }).first {
    // TODO: your code here...
}

Ответ 7

мои два цента за OSX (предыдущие ответы касаются UIKit..)

это работает и для OSX:

final private func getConstraintForButton(){
    let constraints  = self.myButton.constraints
    for constraint in constraints  {
        if constraint.identifier == "redBoxWidth" {
            constraint.constant = 300
            break
        }
    }
}

Примечание. Кажется, что НЕ работает с пользовательским NSView, вместо этого...