启用+禁用自动布局约束

Ran*_*oms 31 nslayoutconstraint swift

我有一个简单的(我认为)问题:我有一个UIImageView,我在故事板中设置了多个约束.

有时,我需要禁用约束,并frame手动设置它,但稍后,我将要重新启用这些约束并让视图返回到约束所决定的位置.

我以为我可以这样做:

@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) 

}
Run Code Online (Sandbox Code Playgroud)

但是,有了这个,我得到了错误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]>.有谁知道为什么会出现这个错误?

view通过调用添加约束来self.view.addConstraint(...)消除错误,但仍然没有将图像视图带回到它应该的位置.

我注意到我甚至不必删除或停用约束,以便能够设置imageView没有问题的框架,只要我不打电话setTranslatesAutoresizingMaskIntoConstraints(true).

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

我也看到了这个问题,但这并没有涵盖可以重新启用的约束 - 只能禁用它们.

试图设置active属性:

self.top.active = false
self.right.active = false
self.bottom.active = false
self.left.active = false

imageView.frame = CGRectMake(100, 100, 100, 100)
Run Code Online (Sandbox Code Playgroud)

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

但真正的问题是,当我尝试让图像视图返回到原来的位置时,通过将所有约束的active属性设置为true,没有任何反应 - 图像视图保持原样(在这种情况下,由...指定)imageView.frame = CGRectMake(100, 100, 100, 100).

此外,根据我的测试和JoachimBøggild 在这里的回答,似乎当约束的active属性设置为false时,该约束变为零,因此无法重新激活.

向数组添加约束并激活/停用它们:

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

Ran*_*oms 64

啊哈!

一旦将其active属性设置为false ,约束将变为零(因此无法重新激活).使它们成为强有力的参考(感谢,Caleb,用于清除命名法)保留它们,以便可以根据需要激活和停用它们.

  • 如果有人想知道如何使 `IBOutlet` 变得强大:只需删除 `weak` 关键字,瞧:你的引用很强! (2认同)

Cal*_*leb 31

如果您查看文档,NSLayoutConstraint您将找到一个名为" 激活和取消激活约束"的部分来描述该active属性,该部分反过来告诉您:

您可以通过更改此属性来激活或取消激活约束...激活或取消激活约束会调用addConstraint:和removeConstraint:在视图上,该视图是此约束管理的项目的最近共同祖先.使用此属性而不是直接调用addConstraint:或removeConstraint:.

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

  • @Randoms让出口"强大"实际上是正确答案,至少这是我的问题.你应该把它作为一个答案发布,而不是作为一个很难找到的评论.或者将其更新为问题本身的一部分. (6认同)
  • 啊,明白了.使强制键入的出口固定它 - 我现在可以正确激活和停用它们. (5认同)
  • 强引用,不是强类型.这是有道理的,因为文档说改变`active`属性会删除约束,这意味着约束所附加的视图不再存在.如果没有强引用,则会释放约束.让你的出口强大避免这种情况. (3认同)
  • 似乎当约束的"active"设置为false时,该约束变为nil,因此无法重新激活. (2认同)