启用 + 禁用自动布局约束

Enable + Disable Auto-Layout Constraints

我有一个简单的(我认为)问题:我有一个 UIImageView,我在情节提要中为其设置了多个约束。

有时,我需要禁用约束并手动设置其 frame,但稍后,我想重新启用这些约束并将视图 return 设置为它是由约束决定的。

我想我可以用类似的东西来做到这一点:

@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var constraint: NSLayoutConstraint!

func example() { 

    //to set its location and size manually
    imageView.removeConstraint(constraint) 
    imageView.frame = CGRectMake(...)

    //to cause it to return to its original position
    imageView.addConstraint(constraint) 

}

然而,有了这个,我得到了错误 2015-08-26 01:14:55.417 Constraints[18472:923024] The view hierarchy is not prepared for the constraint: <NSLayoutConstraint:0x7fbb72815f90 V:[_UILayoutGuide:0x7fbb72814c20]-(100)-[UIImageView:0x7fbb72814540]>。有谁知道为什么会出现这个错误?

通过调用 self.view.addConstraint(...) 将约束添加到 view 可以消除错误,但仍然无法将图像视图恢复到应有的位置。

我注意到我什至不必删除或停用约束就可以毫无问题地设置 imageView 的框架,只要我不调用 setTranslatesAutoresizingMaskIntoConstraints(true)

我已经看过 this 问题,但答案似乎不必要地复杂,可能已经过时,甚至不适用。

我也看到了 this 问题,但这不包括可以重新启用的约束——只包括如何禁用它们。

正在尝试设置 active 属性:

self.top.active = false
self.right.active = false
self.bottom.active = false
self.left.active = false
    
imageView.frame = CGRectMake(100, 100, 100, 100)

这实际上只会导致 imageView 不再可见。 (但是,如果我没有将所有约束 active 属性 设置为 false,imageView 会移动到正确的位置。

但真正的问题是,当我尝试将图像视图 return 设置到它原来的位置时,通过将所有约束 active 属性 设置为 true,没有任何反应——imageView 保持原样(在本例中由 imageView.frame = CGRectMake(100, 100, 100, 100).

指定

此外,根据我的测试和 Joachim Bøggild 的回答 here,当约束的 active 属性 设置为 false 时,该约束似乎变为 nil,因此无法重新激活。

向数组添加约束并activating/deactivating它们:

有趣的是,这会导致与设置 active 属性 几乎完全相同的问题。将所有约束放在数组 array 中,然后调用 NSLayoutConstraint.deactivateConstraints(array) 使图像视图消失。此外,稍后使用 NSLayoutConstraint.activateConstraints(array) 重新激活约束不会使图像视图 return 到它应该的位置——它停留在原来的位置。

如果您查看 NSLayoutConstraint 的文档,您会找到一个名为 Activating and Deactivating Constraints that describes the active property 的部分,它反过来告诉您:

You can activate or deactivate a constraint by changing this property...Activating or deactivating the constraint calls addConstraint: and removeConstraint: on the view that is the closest common ancestor of the items managed by this constraint. Use this property instead of calling addConstraint: or removeConstraint: directly.

因此,一旦您获得了对相关约束的 strong 引用(例如您的插座),您只需将其设置为 active 属性 到 false(或 Obj-C 中的 NO)禁用,或 true(或 YES)启用。

将约束作为 IBOutlet 从故事板连接到 ViewController 并创建一个数组,在数组中添加所有约束。

在不使用时停用这些约束。

使用时添加约束。

NSLayoutConstraint *constraint1;
NSLayoutConstraint *constraint2;
NSLayoutConstraint *constraint3;
NSArray *arr = @[constraint1,constraint2,constraint3];
 [NSLayoutConstraint deactivateConstraints:arr];

//After deactivate constraint array add what ever frame you want to add

//Activate  lateroN
[NSLayoutConstraint activateConstraints:arr];

啊哈!

一旦 active 属性 设置为 false,约束将变为 nil(因此无法重新激活)。使它们成为 强引用 (感谢 Caleb,清理了术语)保留它们,以便可以根据需要激活和停用它们。