Есть ли способ добавить идентификатор в 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 вы можете сделать это в раскадровке:
![введите описание изображения здесь]()
-
Однако, если вы настроите свое ограничение в коде, сделайте следующее:
let constraint = NSLayoutConstraint()
constraint.identifier = "identifier"
-
Для этих ограничений, которые вы настроили в раскадровке, но вы должны установить идентификатор в коде:
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, вместо этого...