【问题标题】:Do you have to set translatesAutoresizingMaskIntoConstraints to false for a ViewController's 'main' view?对于 ViewController 的“主”视图,您是否必须将 translatesAutoresizingMaskIntoConstraints 设置为 false?
【发布时间】:2021-05-17 10:09:18
【问题描述】:

我在 Xcode 中有一个空白的 Swift 项目,并且没有使用故事板。我在 viewDidLoad 下的代码中添加了一个视图:

var view1 = UIView()
view1.backgroundColor = .red
view.addSubview(view1)
view1.translatesAutoresizingMaskIntoConstraints = false

然后我添加约束:

NSLayoutConstraint.activate([
            view1.topAnchor.constraint(equalTo: view.topAnchor, constant: 20),
            view1.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
            view1.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),
            view1.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -20)
        ])

视图加载并在模拟器中看起来很好。但是我在另一个项目中遇到了一些其他视图的问题,所以我构建了上面的测试。所以我发现,即使上面的构建和工作,如果我使用以下方法检查不明确的布局:

print(view1.hasAmbiguousLayout)

我记录了错误:

2021-02-14 15:26:34.919048+1100 自动布局扩展[6603:4438601] [LayoutConstraints] 视图的布局不明确。请参阅“自动布局 Guide: Ambiguous Layouts”以帮助调试。显示来自的概要 调用 -[UIView _autolayoutTrace] 以提供更多详细信息。

*UIView:0x13360c3b0- UIView 的模糊布局:0x13360c3b0.Width{id: 9}, UIView:0x13360c3b0.Height{id: 12}

图例:* - 自动布局 + - 手动布局, 但在布局引擎中表示,因为 translatesAutoresizingMaskIntoConstraints = YES • - 布局引擎 主机真

我可以让这些错误不被记录的唯一方法是同时设置 ViewController 的主视图,如下所示:

view.translatesAutoresizingMaskIntoConstraints = false

通过这样做,我知道得到以下日志输出:

所以我的问题是......我没有在 Apple 的文档(或这里,谷歌搜索等)中读到任何地方说你必须将 viewController 的 view.translatesAutoresizingMaskIntoConstraints 设置为 false。我错过了什么吗?抱歉,如果这只是我的理解,但最好澄清一下。

【问题讨论】:

  • 是的。如果要手动设置约束,则需要将该变量设置为 false。如果你没有设置,UIKit 会尝试自动找出给定自动布局的必要约束。您可以在官方文档中阅读。 developer.apple.com/documentation/uikit/uiview/…
  • 谢谢。是的,我读过它,但它并没有真正谈论超级视图。而且我并没有真正尝试控制/管理超级视图约束/大小等。这让我感到困惑。

标签: ios swift autolayout


【解决方案1】:

首先,您永远不应该在视图控制器的主视图上设置.translatesAutoresizingMaskIntoConstraints = false(除非您将控制器作为孩子加载,但这不是您在问题中所说的)。

您需要阅读视图/视图控制器生命周期。

viewDidLoad() 中,自动布局尚未运行以管理视图和子视图布局。

viewDidLayoutSubview() 中,自动布局HAS 运行,但根据您的设计的动态程度(以及其他因素),这可能会被多次调用。

viewDidAppear() 中,所有布局都已完成(除非您的代码正在运行异步进程来动画视图、添加其他视图等)。

所以,尝试运行这个简单的示例 - 它会打印当前执行函数的名称以及来自 .hasAmbiguousLayout 的输出:

class TestLayoutViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        var view1 = UIView()
        view1.backgroundColor = .red
        view.addSubview(view1)
        view1.translatesAutoresizingMaskIntoConstraints = false
        
        NSLayoutConstraint.activate([
            view1.topAnchor.constraint(equalTo: view.topAnchor, constant: 20),
            view1.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
            view1.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),
            view1.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -20)
        ])
        
        print() // blank line
        print(#function)
        print() // blank line
        print("In viewDidLoad(), does subview have ambigous layout?")
        print(view1.hasAmbiguousLayout)

    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        
        guard let v = view.subviews.first else {
            return
        }
        
        print() // blank line
        print(#function)
        print() // blank line
        print("In viewDidLayoutSubviews(), does subview have ambigous layout?")
        print(v.hasAmbiguousLayout)
        
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        guard let v = view.subviews.first else {
            return
        }
        
        print() // blank line
        print(#function)
        print() // blank line
        print("In viewDidAppear(), does subview have ambigous layout?")
        print(v.hasAmbiguousLayout)
        
    }
    
}

这是您应该在调试控制台中看到的内容:

viewDidLoad()

In viewDidLoad(), does subview have ambigous layout?
2021-02-14 08:41:46.694337-0500 PanZoom[43869:6978294] [LayoutConstraints] View has an ambiguous layout. See "Auto Layout Guide: Ambiguous Layouts" for help debugging. Displaying synopsis from invoking -[UIView _autolayoutTrace] to provide additional detail.

*UIView:0x7fd472604960- AMBIGUOUS LAYOUT for UIView:0x7fd472604960.Width{id: 90}, UIView:0x7fd472604960.Height{id: 93}

Legend:
    * - is laid out with auto layout
    + - is laid out manually, but is represented in the layout engine because translatesAutoresizingMaskIntoConstraints = YES
    • - layout engine host
true

viewDidLayoutSubviews()

In viewDidLayoutSubviews(), does subview have ambigous layout?
false

viewDidAppear(_:)

In viewDidAppear(), does subview have ambigous layout?
false

如您所见,在viewDidLoad() 期间,我们会遇到自动布局模糊,但不会viewDidLayoutSubviews()viewDidAppear() 中。

【讨论】:

  • 感谢您的澄清和提醒。这里的微妙之处在于,尽管可以在viewDidLoad() 中设置约束,但直到viewDidLayoutSubview() 才真正应用它们——谢谢。不管我读了多少关于自动布局引擎的内容,它都是一个难以掌握的野兽。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-06
相关资源
最近更新 更多