为什么这个 UILabel 的水平位置不能用自动布局动态更新?

Why can't this UILabel's horizontal position be updated dynamically with Auto Layout?

我有一个 UILabel 插座,它的顶部 space 到超级视图,前导 space 到超级视图在故事板中设置为 20。我想按一个按钮来动态更改约束以垂直和水平居中。垂直动态变化工作正常,但水平动态变化没有任何变化:

@IBAction func moveLabel(sender: AnyObject) {
    self.view.addConstraint(NSLayoutConstraint(
        item: self.label,
        attribute: NSLayoutAttribute.CenterY,
        relatedBy: NSLayoutRelation.Equal,
        toItem: self.view,
        attribute: NSLayoutAttribute.CenterY,
        multiplier: 1,
        constant: 0))

    self.view.addConstraint(NSLayoutConstraint(
        item: self.label,
        attribute: NSLayoutAttribute.CenterX,
        relatedBy: NSLayoutRelation.Equal,
        toItem: self.view,
        attribute: NSLayoutAttribute.CenterX,
        multiplier: 1,
        constant: 0))
}

水平间距保持在 20 超视图领先,但垂直间距已正确应用以居中。为什么水平居中不起作用?

如果情节提要中已经有一个顶级约束,则需要停用该约束才能应用新约束,以免发生崩溃。

您不应该在每次要移动标签时都添加约束。您应该只添加一次约束,在 viewDidLoad 甚至情节提要中,为它们创建 IBOutlets 并相应地 activate/deactivate 它们。

因此您的代码将如下所示:

@IBOutlet weak var topOffsetConstraint : NSLayoutConstraint 
@IBOutlet weak var leadingOffsetConstraint : NSLayoutConstraint
@IBOutlet weak var horizontalCenterConstraint : NSLayoutConstraint
@IBOutlet weak var verticalOffsetConstraint : NSLayoutConstraint

@IBAction func moveLabel(sender: AnyObject) {
     topOffsetConstranint.active = NO;
     leadingOffsetConstraint.active = NO;
     horizontalCenterConstraint.active = YES;
     verticalOffsetConstraint.active = YES;

     // If you don't need to animate the changes, remove the animation block
     UIView.animateWithDuration(0.3) {
           self.view.layoutIfNeeded();
     }
}

我假设您想要来回移动标签。如果不是这种情况并且您的 moveLabel 方法只被调用一次,您的代码应该可以工作。只需确保停用情节提要中设置的约束并调用 layoutIfNeeded(如果您需要,可以在动画块中调用)。

希望这对您的问题有所帮助!让我知道进展如何