有没有办法在 Interface Builder 的自动布局约束中添加标识符?

Is there a way to add an identifier to Auto Layout Constraints in Interface Builder?

在 Interface Builder 中做了一些视觉布局后,我创建了一些我想在运行时访问的约束。有没有办法在 Interface Builder 中标记或识别约束,以便以后可以查找它们?

我想这样做的原因是我需要根据视觉指定的约束执行一些计算。我知道 Apple 提供了 Visual Format Language 并且我可以在控制器中以编程方式指定约束。我宁愿不使用这种方法,这样我就不会失去 IB 的设计时反馈。

编辑

创建引用插座确实有效,但问题仍然存在。

更新:

正如 Bartłomiej Semańczyk 在 中所解释的,现在 Identifier 字段在 Attributes Inspector 中可见NSLayoutConstraint 无需自己公开此字段。只需在 Document Outline 视图或 Storyboard 视图中 select 约束,然后在右侧的 Attributes Inspector 中添加标识符.


较早的答案:

是的,这是可以做到的。 NSLayoutConstraint 有一个名为 identifier 的 属性,可以在 Interface Builder 中公开并分配。为了对此进行演示,我创建了一个 单视图应用程序 ,它有一个红色框子视图。这个子视图有 4 个约束:宽度、高度、在容器中水平居中、在容器中垂直居中。我通过执行以下操作为宽度约束提供了标识符 redBoxWidth

  1. 单击文档布局视图中的宽度限制。然后在 Identity Inspector User Defined Runtime Attributes 下,点击 Key Path[=56] 下的 + =].将 keyPath 更改为 identifier,将 Type Boolean 更改为String,并将 Value 设置为 redBoxWidth

  2. 然后在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
                    }
                }
            }
        }
    }
    

获取自动布局约束的 IBOutlet。

NSLayoutConstraint class.

中有一个 属性 叫做 constant

例如,您已经从您的 IB 中获取了任何视图的 IBOutlet 高度约束,并且您想要以编程方式更改它的高度,您需要做的就是:

 constraint.constant = isMoreHeight ? height1 : height2;

完成此操作后,您需要更新父视图的视图层次结构中的所有其他视图。为此,您需要在下面的行中写下:

[self setLayoutIfNeeded];

为了更好的用户体验,您可以将此行放在动画块中以获得更平滑的过渡效果,

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

希望这对您有所帮助..

只是添加到@vacawama 的回答中。您可以编写一个 UIView 类别并使用一个简单的函数提取约束,而不是在您需要找到约束的任何地方循环 copy/pasting:

.h 文件:

#import <UIKit/UIKit.h>

@interface UIView (EasyAutolayout)

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

@end

.m 文件:

#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
  1. 从 Xcode 7 开始,您可以在情节提要中完成:

  1. 但是,如果您在代码中设置约束,请执行以下操作:

    let constraint = NSLayoutConstraint() 
    constraint.identifier = "identifier"
    
  2. 对于这些你已经在故事板中设置的约束,但是你必须在代码中设置标识符:

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

这个怎么样:

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

您还可以 link 对控制器的属性进行约束,就像对任何其他组件所做的那样。只需按住 ctrl 键将其拖到您的代码中即可:

然后它可以在您的控制器代码中访问为 属性:

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

您可以更改它的值,例如:

self.myConstraint.constant=100.;

我的两分钱 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,而是...