删除影响 UIView 的所有约束 [英] Remove all constraints affecting a UIView

查看:38
本文介绍了删除影响 UIView 的所有约束的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 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.此外,我需要确保在正确的视图上调用我删除约束的调用.例如,假设 myViewsLeftConstraintviewA 所有.如果我不小心调用了 [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.constraintsself.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:

        • C0:我:和儿子一样(归我所有)
        • C1:我:宽度 = 100(归我所有)
        • C2:我:和哥哥一样高(父亲拥有)
        • C3:我:和叔叔同款(祖父所有)
        • C4:我:和祖父一样左(祖父所有)
        • C5:兄弟:与父亲同左(父亲拥有)
        • C6:叔叔:与祖父同左(祖父所有)
        • C7:儿子:和女儿一样左(归我所有)

        现在假设我们要移除所有影响 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 是我),我将得到 [C2,C5],因为这些是父亲拥有的约束.显然我们不能删除所有这些,因为 C5Me 完全无关.

        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.

        蛮力方法是遍历每个视图的祖先(包括它自己),并查看 firstItemsecondItem 是否是视图本身;如果是这样,请删除该约束.这将导致正确的解决方案,返回 [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 的所有约束的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆