我有一个 UIView,它通过几个约束放置在屏幕上.一些约束归父视图所有,其他约束归其他祖先所有(例如,可能是 UIViewController 的视图属性).
I have a UIView which is placed on the screen via several constraints. Some of the constraints are owned by the superview, others are owned by other ancestors (e.g. perhaps the view property of a UIViewController).
我想删除所有这些旧约束,并使用新约束将其放置在新的地方.
I want to remove all of these old constraints, and place it somewhere new using new constraints.
如何在不为每个约束创建 IBOutlet 并且不必记住哪个视图拥有所述约束的情况下做到这一点?
How can I do this without creating an IBOutlet for every single constraint and having to remember which view owns said constraint?
详细地说,天真的方法是为每个约束创建一堆 IBOutlets,然后会涉及调用代码,例如:
To elaborate, the naive approach would be to create a bunch of IBOutlets for each of the constraints, and would then involve calling code such as:
[viewA removeConstraint:self.myViewsLeftConstraint];
[viewB removeConstraint:self.myViewsTopConstraint];
[viewB removeConstraint:self.myViewsBottomConstraint];
[self.view removeConstraint:self.myViewsRightConstraint];
这段代码的问题是,即使在最简单的情况下,我也需要创建 2 个 IBOutlets.对于复杂的布局,这可以轻松达到 4 或 8 个所需的 IBOutlets.此外,我需要确保在正确的视图上调用删除约束的调用.例如,假设 myViewsLeftConstraint
归 viewA
所有.如果我不小心调用了 [self.view removeConstraint:self.myViewsLeftConstraint]
,什么都不会发生.
The problem with this code is that even in the simplest case, I would need to create 2 IBOutlets. For complex layouts, this could easily reach 4 or 8 required IBOutlets. Furthermore, I would need to ensure that my call to remove the constraint is being called on the proper view. For example, imagine that myViewsLeftConstraint
is owned by viewA
. If I were to accidentally call [self.view removeConstraint:self.myViewsLeftConstraint]
, nothing would happen.
注意:方法constraintsAffectingLayoutForAxis 看起来很有希望,但仅用于调试目的.
Note: The method constraintsAffectingLayoutForAxis looks promising, but is intended for debugging purposes only.
更新:我收到的许多答案都涉及 self.constraints
、self.superview.constraints
或其中的一些变体.这些解决方案不起作用,因为这些方法只返回视图拥有的约束,而不是影响视图的约束.
Update: Many of the answers I am receiving deal with self.constraints
, self.superview.constraints
, or some variant of those. These solutions won't work since those methods return only the constraints owned by the view, not the ones affecting the view.
要阐明这些解决方案的问题,请考虑以下视图层次结构:
To clarify the problem with these solutions, consider this view hierarchy:
现在假设我们创建了以下约束,并始终将它们附加到它们最近的共同祖先:
Now imagine we create the following constraints, and always attach them to their nearest common ancestor:
现在假设我们想要移除所有影响 Me
的约束.任何适当的解决方案都应该删除 [C0,C1,C2,C3,C4]
,仅此而已.
Now imagine we want to remove all constraints affecting Me
. Any proper solution should remove [C0,C1,C2,C3,C4]
and nothing else.
如果我使用 self.constraints
(self 是我),我将得到 [C0,C1,C7]
,因为这些是我拥有的唯一约束.显然,删除它是不够的,因为它缺少 [C2,C3,C4]
.此外,它会不必要地删除 C7
.
If I use self.constraints
(where self is Me), I will get [C0,C1,C7]
, since those are the only constraints owned by Me. Obviously it wouldn't be enough to remove this since it is missing [C2,C3,C4]
. Furthermore, it is removing C7
unnecessarily.
如果我使用 self.superview.constraints
(其中 self 是 Me),我将得到 [C2,C5]
,因为这些是父亲拥有的约束.显然我们无法删除所有这些,因为 C5
与 Me
完全无关.
If I use self.superview.constraints
(where self is Me), I will get [C2,C5]
, since those are the constraints owned by Father. Obviously we cannot remove all these since C5
is completely unrelated to Me
.
如果我使用 grandfather.constraints
,我会得到 [C3,C4,C6]
.同样,我们不能删除所有这些,因为 C6
应该保持原样.
If I use grandfather.constraints
, I will get [C3,C4,C6]
. Again, we cannot remove all of these since C6
should remain intact.
蛮力方法是遍历每个视图的祖先(包括它自己),并查看 firstItem
或 secondItem
是否是视图本身;如果是这样,请删除该约束.这将导致正确的解决方案,返回 [C0,C1,C2,C3,C4]
,并且只返回那些约束.
The brute force approach is to loop over each of the view's ancestors (including itself), and seeing if firstItem
or secondItem
are the view itself; if so, remove that constraint. This will lead to a correct solution, returning [C0,C1,C2,C3,C4]
, and only those constraints.
但是,我希望有一个比遍历整个祖先列表更优雅的解决方案.
However, I'm hoping there is a more elegant solution than having to loop through the entire list of ancestors.
目前我发现的唯一解决方案是从其父视图中删除视图:
The only solution I have found so far is to remove the view from its superview:
[view removeFromSuperview]
这看起来像是移除了影响其布局的所有约束,并准备好添加到超级视图并附加新的约束.但是,它也会错误地从层次结构中删除任何子视图,并错误地删除 [C7]
.
This looks like it removes all constraints affecting its layout and is ready to be added to a superview and have new constraints attached. However, it will incorrectly remove any subviews from the hierarchy as well, and get rid of [C7]
incorrectly.
这篇关于移除所有影响 UIView 的约束的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!