草庐IT

ios - 移除所有影响 UIView 的约束

coder 2023-04-25 原文

我有一个 UIView,它通过几个约束放置在屏幕上。一些约束归父 View 所有,其他约束归其他祖先所有(例如,可能是 UIViewController 的 View 属性)。

我想删除所有这些旧约束,并使用新约束将其放置在新的地方。

如何在不为每个约束创建 IBOutlet 并且不必记住哪个 View 拥有所述约束的情况下做到这一点?

详细地说,天真的方法是为每个约束创建一堆 IBOutlets,然后会涉及调用代码,例如:

[viewA removeConstraint:self.myViewsLeftConstraint];
[viewB removeConstraint:self.myViewsTopConstraint];
[viewB removeConstraint:self.myViewsBottomConstraint];
[self.view removeConstraint:self.myViewsRightConstraint];

这段代码的问题是,即使在最简单的情况下,我也需要创建 2 个 IBOutlets。对于复杂的布局,这可以轻松达到 4 或 8 个所需的 IBOutlets。此外,我需要确保在正确的 View 上调用删除约束的调用。例如,假设 myViewsLeftConstraintviewA 所有。如果我不小心调用了 [self.view removeConstraint:self.myViewsLeftConstraint],什么都不会发生。

注意:方法constraintsAffectingLayoutForAxis看起来很有希望,但仅用于调试目的。


更新:我收到的许多答案都涉及 self.constraintsself.superview.constraints 或其中的一些变体.这些解决方案不起作用,因为这些方法只返回 View 拥有的约束,而不是影响 View 的约束。

要阐明这些解决方案的问题,请考虑以下 View 层次结构:

  • 祖父
    • 父亲
        • 儿子
        • 女儿
      • 兄弟
    • 大叔

现在假设我们创建了以下约束,并始终将它们附加到它们最近的共同祖先:

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

现在假设我们想要移除所有影响 Me 的约束。任何适当的解决方案都应该删除 [C0,C1,C2,C3,C4] ,仅此而已。

如果我使用 self.constraints(self 是我),我将得到 [C0,C1,C7],因为这些是我拥有的唯一约束.显然,删除它是不够的,因为它缺少 [C2,C3,C4]。此外,它会不必要地删除 C7

如果我使用 self.superview.constraints(其中 self 是 Me),我将得到 [C2,C5],因为这些是父亲拥有的约束。显然我们无法删除所有这些,因为 C5Me 完全无关。

如果我使用 grandfather.constraints,我会得到 [C3,C4,C6]。同样,我们不能删除所有这些,因为 C6 应该保持原样。

蛮力方法是遍历每个 View 的祖先(包括它自己),并查看 firstItemsecondItem 是否是 View 本身;如果是这样,请删除该约束。这将导致正确的解决方案,返回 [C0,C1,C2,C3,C4],并且只返回那些约束。

但是,我希望有一个比遍历整个祖先列表更优雅的解决方案。

最佳答案

这种方法对我有用:

@interface UIView (RemoveConstraints)

- (void)removeAllConstraints;

@end


@implementation UIView (RemoveConstraints)

- (void)removeAllConstraints
{
    UIView *superview = self.superview;
    while (superview != nil) {
        for (NSLayoutConstraint *c in superview.constraints) {
            if (c.firstItem == self || c.secondItem == self) {
                [superview removeConstraint:c];
            }
        }
        superview = superview.superview;
    }

    [self removeConstraints:self.constraints];
    self.translatesAutoresizingMaskIntoConstraints = YES;
}

@end

执行完成后,您的 View 会保持在原来的位置,因为它会创建自动调整大小的约束。当我不这样做时, View 通常会消失。此外,它不仅从父 View 中移除约束,而且一直向上遍历,因为在祖先 View 中可能存在影响它的约束。


Swift 4 版本

extension UIView {
    
    public func removeAllConstraints() {
        var _superview = self.superview
        
        while let superview = _superview {
            for constraint in superview.constraints {
                
                if let first = constraint.firstItem as? UIView, first == self {
                    superview.removeConstraint(constraint)
                }
                
                if let second = constraint.secondItem as? UIView, second == self {
                    superview.removeConstraint(constraint)
                }
            }
            
            _superview = superview.superview
        }
        
        self.removeConstraints(self.constraints)
        self.translatesAutoresizingMaskIntoConstraints = true
    }
}

关于ios - 移除所有影响 UIView 的约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24418884/

有关ios - 移除所有影响 UIView 的约束的更多相关文章

  1. ruby - 如何以所有可能的方式将字符串拆分为长度最多为 3 的连续子字符串? - 2

    我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123

  2. ruby-on-rails - 跳过状态机方法的所有验证 - 2

    当我的预订模型通过rake任务在状态机上转换时,我试图找出如何跳过对ActiveRecord对象的特定实例的验证。我想在reservation.close时跳过所有验证!叫做。希望调用reservation.close!(:validate=>false)之类的东西。仅供引用,我们正在使用https://github.com/pluginaweek/state_machine用于状态机。这是我的预订模型的示例。classReservation["requested","negotiating","approved"])}state_machine:initial=>'requested

  3. ruby - Nokogiri 剥离所有属性 - 2

    我有这个html标记:我想得到这个:我如何使用Nokogiri做到这一点? 最佳答案 require'nokogiri'doc=Nokogiri::HTML('')您可以通过xpath删除所有属性:doc.xpath('//@*').remove或者,如果您需要做一些更复杂的事情,有时使用以下方法遍历所有元素会更容易:doc.traversedo|node|node.keys.eachdo|attribute|node.deleteattributeendend 关于ruby-Nokog

  4. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  5. ruby - 获取模块中定义的所有常量的值 - 2

    我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c

  6. Ruby 文件 IO 定界符? - 2

    我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的

  7. ruby-on-rails - 添加回形针新样式不影响旧上传的图像 - 2

    我有带有Logo图像的公司模型has_attached_file:logo我用他们的Logo创建了许多公司。现在,我需要添加新样式has_attached_file:logo,:styles=>{:small=>"30x15>",:medium=>"155x85>"}我是否应该重新上传所有旧数据以重新生成新样式?我不这么认为……或者有什么rake任务可以重新生成样式吗? 最佳答案 参见Thumbnail-Generation.如果rake任务不适合你,你应该能够在控制台中使用一个片段来调用重新处理!关于相关公司

  8. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

  9. .net - .NET 将如何影响 Python 和 Ruby 应用程序? - 2

    我很好奇.NET将如何影响Python和Ruby应用程序。用IronPython/IronRuby编写的应用程序是否会非常特定于.NET环境,以至于它们实际上将变得特定于平台?如果他们不使用任何.NET功能,那么IronPython/IronRuby相对于非.NET同类产品的优势是什么? 最佳答案 我不能说任何关于IronRuby的东西,但是大多数Python实现(如IronPython、Jython和PyPy)都试图尽可能忠实于CPython实现。不过,IronPython正在迅速成为这方面的佼佼者之一,并且在PlanetPyth

  10. ruby - 如何遍历 Ruby 中所有正则表达式匹配的字符串? - 2

    我们有一个字符串:“”这个正则表达式://i如何从当前字符串中获取所有匹配项? 最佳答案 "".scan(//)参见scan在ruby​​-docs上 关于ruby-如何遍历Ruby中所有正则表达式匹配的字符串?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/6857852/

随机推荐