由于 iOS 中的 "different" 视图层次结构中的锚点,自动布局约束崩溃,但是

Auto Layout constraint crashes due to anchor in a "different" view hierarchy in iOS, but

我正在 iOS 11.X 应用程序中使用 Swift 4.1,完全程式化的。使用 Xcode 9.4

我正在尝试让视图居中(水平),距离视图顶部 10 点,支持旋转。

应用程序架构有规律的东西,如下(没有故事板):

鉴于在横向模式下,statusBar 不可见,为了简化自动布局配置,我决定按如下方式向 navigationBar 添加顶部锚点(为清楚起见简化了代码) :

let navBar = self.navigationController!.navigationBar
let label = UILabel()
label.backgroundColor = .yellow
label.text = "TEXT"
label.textAlignment = NSTextAlignment.center
self.view.addSubview(label)
label.translatesAutoresizingMaskIntoConstraints = false
label.widthAnchor.constraint(equalToConstant: 50).isActive = true
label.heightAnchor.constraint(equalToConstant: 20).isActive = true
label.centerXAnchor.constraint(equalTo: label.superview!.centerXAnchor).isActive = true
label.topAnchor.constraint(equalTo: navBar.bottomAnchor, constant: 10).isActive = true

结果符合预期。它旋转得很好,如果应用程序以横向或纵向启动(在设备和模拟器中)也能正常工作。

肖像

风景

现在。 FastForward 1 在 GitHub 中提交,整体 App View 架构没有变化,代码相同,它崩溃并显示以下消息

*** NSGenericException', reason: '无法激活带有锚点的约束,因为它们没有共同的祖先。约束或其锚点是否引用不同视图层次结构中的项目?那是违法的。

知道这里发生了什么吗?我从之前的 GitHub 提交中下载了 .zip 以将其隔离并重新确认它是否有效!!但是当前提交失败,没有更改与此相关的代码 UILabel.

导航栏是 UIWindow->UILayoutContainerView->UINavigationBar

的一部分

我能够确定导致崩溃的原因。

最后一次提交的唯一区别是稍有延迟(在添加 UI 元素和约束之前)。 0.01 秒就足够了,效果如下:

import UIKit
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        self.title = "APP TITLE"
        self.view.backgroundColor = .white
        Timer.scheduledTimer(withTimeInterval: 0.01, repeats: false) { (nil) in
            let navBar = self.navigationController!.navigationBar
            let label = UILabel()
            label.backgroundColor = .yellow
            label.text = "TEXT"
            label.textAlignment = NSTextAlignment.center
            self.view.addSubview(label)
            label.translatesAutoresizingMaskIntoConstraints = false
            label.widthAnchor.constraint(equalToConstant: 50).isActive = true
            label.heightAnchor.constraint(equalToConstant: 20).isActive = true
            label.centerXAnchor.constraint(equalTo: label.superview!.centerXAnchor).isActive = true
            label.topAnchor.constraint(equalTo: navBar.bottomAnchor, constant: 10).isActive = true
        }
    }
}

您将在此处找到一个干净的 Xcode 项目和工作代码 https://www.dropbox.com/s/vhd9emd8ixf5lbs/AutoLO.zip?dl=0

评论 Timer.scheduledTimer(withTimeInterval: repeats:) 行,它将崩溃并显示消息:

*** 由于未捕获的异常 'NSGenericException' 而终止应用程序,原因:'无法使用锚 NSLayoutYAxisAnchor:0x60c000267e80 "UILabel:0x7fe0ede0b960'TEXT'.top" 和 NSLayoutYAxisAnchor:0x60c000267f00 "UINavigationBar:0x7fe0edd06ce0.bottom" 激活约束因为他们没有共同的祖先。约束或其锚点是否引用不同视图层次结构中的项目?这是违法的。

为什么 Xcode 在存在 none 时抱怨 centerY / YAxis 锚点的解释对我来说是个谜。