【问题标题】:iOS Autolayout constrain issue | App crashingiOS 自动布局约束问题 |应用程序崩溃
【发布时间】:2017-10-23 15:38:02
【问题描述】:

我正在尝试在运行时向屏幕的子视图添加约束。这导致崩溃。以下是我的代码:

for var i in 0 ..< 5{
        let aController = storyboard.instantiateViewController(withIdentifier: "design")
        let itemView = aController.view
        //itemView!.frame.origin.x = CGFloat(i) * itemView!.frame.width
        itemView!.translatesAutoresizingMaskIntoConstraints = false

        itemView!.addConstraint(NSLayoutConstraint(item: scrollView, attribute: .trailing, relatedBy: .equal, toItem: itemView!, attribute: .trailing, multiplier: 1, constant: 20))
        itemView!.addConstraint(NSLayoutConstraint(item: scrollView, attribute: .leading, relatedBy: .equal, toItem: itemView!, attribute: .leading, multiplier: 1, constant: 0))
        itemView!.addConstraint(NSLayoutConstraint(item: scrollView, attribute: .top, relatedBy: .equal, toItem: itemView!, attribute: .top, multiplier: 1, constant: 20))
        itemView!.addConstraint(NSLayoutConstraint(item: scrollView, attribute: .bottom, relatedBy: .equal, toItem: itemView!, attribute: .bottom, multiplier: 1, constant: 20))

        scrollView.addSubview(itemView!)
    }

我得到的错误如下:

2017-10-23 10:39:37.087674+0530 RollerCoasterPotential[998:22689] [LayoutConstraints] 视图层次结构没有为 约束:

当添加到视图时,约束的项必须是 该视图(或视图本身)。如果约束,这将崩溃 需要在组装视图层次结构之前解决。打断 -[UIView(UIConstraintBasedLayout) _viewHierarchyUnpreparedForConstraint:] 进行调试。

2017-10-23 10:39:37.087924+0530 RollerCoasterPotential[998:22689] * -[UIView 中的断言失败 _layoutEngine_didAddLayoutConstraint:roundingAdjustment:mutuallyExclusiveConstraints:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3688.4/NSLayoutConstraint_UIKitAdditions.m:734 2017-10-23 10:39:37.177966+0530 RollerCoasterPotential[998:22689] * 由于未捕获的异常而终止应用程序 'NSInternalInconsistencyException',原因:'无法设置 视图层次结构的布局没有为约束做好准备。'

【问题讨论】:

  • scrollView在ViewController中是如何定义和添加的?
  • ScrollView 是通过 Interface Builder 添加的(不是动态添加的)。
  • 首先,我认为您不需要为滚动视图将 translatesAutoresizingMaskIntoConstraints 设置为 false。您应该为每个 itemView 将其设置为 false。其次,如果你使用 Autolayout,你不需要设置 itemview 的 frame 的原点。第三,您应该为 itemview 创建自动布局约束(以满足位置和大小,而不仅仅是尾随约束)并将其添加到滚动视图。不要这样做。
  • 请查看更新后的代码@PuneetSharma。我仍然遇到同样的错误。
  • 包括一个回答

标签: ios swift autolayout


【解决方案1】:

试试这个:

func addConstraints() {
    var itemViews:[UIView] = []
    for i in 0 ..< 5 {
        let aController = storyboard!.instantiateViewController(withIdentifier: "design")
        let itemView = aController.view
        itemView!.translatesAutoresizingMaskIntoConstraints = false
        scrollView.addSubview(itemView!)
        itemViews.append(itemView!)
        scrollView.addConstraint(NSLayoutConstraint(item: itemView!, attribute: .trailing, relatedBy: .equal, toItem: scrollView, attribute: .trailing, multiplier: 1, constant: 20))
        scrollView.addConstraint(NSLayoutConstraint(item: itemView!, attribute: .leading, relatedBy: .equal, toItem: scrollView, attribute: .leading, multiplier: 1, constant: 0))

        if(i == 0) {
            scrollView.addConstraint(NSLayoutConstraint(item: itemView!, attribute: .top, relatedBy: .equal, toItem: scrollView, attribute: .top, multiplier: 1, constant: 20))
        } else {
            let previousView = itemViews[i-1]
            itemView!.addConstraint(NSLayoutConstraint(item: previousView!, attribute: .top, relatedBy: .equal, toItem:itemView!, attribute: .top, multiplier: 1, constant: 20))
        }

        if i == 4 {
            scrollView.addConstraint(NSLayoutConstraint(item: itemView!, attribute: .bottom, relatedBy: .equal, toItem: scrollView, attribute: .bottom, multiplier: 1, constant: 20))
        }

    }
}

【讨论】:

  • 所有视图都汇集在一起​​。相互重叠。
  • 不。它使应用程序崩溃。第一个元素应该有固定的顶部、底部、前导和尾随空间,但后续的 itemView 应该只有水平空间。顶部和底部应固定。不是吗?
  • @TechBee:第一项应该对超级视图有顶部、前导、尾随约束。第 2、第 3、第 4 个项目应该有前导,尾随到超级视图和顶部到前一个视图。最后一项(第 5 项),应该有前导,尾随到超级视图,从顶部到上一个视图,底部到超级视图。
  • 这是一个经典问题。 @Puneet 你遇到过这种问题吗?
  • @TechBee:我不知道为什么你所有的观点都聚集在一起。他们不应该。在运行时,您可能会在控制台上收到特定于约束的错误,这可能有助于进一步调试。
【解决方案2】:

您在滚动视图中添加项目之前添加约束。导致以下错误,

'无法使用未准备好约束的视图层次结构设置布局。'

相反,在滚动视图中添加项目,然后应用约束。大概是这样的。 (假设您的其余约束条件都很好。)

for var i in 0 ..< 5{
    let aController = storyboard.instantiateViewController(withIdentifier: "design")
    let itemView = aController.view

    //itemView!.frame.origin.x = CGFloat(i) * itemView!.frame.width
    itemView!.translatesAutoresizingMaskIntoConstraints = false

    //Below add your view

    scrollView.addSubview(itemView!)

    itemView!.addConstraint(NSLayoutConstraint(item: scrollView, attribute: .trailing, relatedBy: .equal, toItem: itemView!, attribute: .trailing, multiplier: 1, constant: 20))
    itemView!.addConstraint(NSLayoutConstraint(item: scrollView, attribute: .leading, relatedBy: .equal, toItem: itemView!, attribute: .leading, multiplier: 1, constant: 0))
    itemView!.addConstraint(NSLayoutConstraint(item: scrollView, attribute: .top, relatedBy: .equal, toItem: itemView!, attribute: .top, multiplier: 1, constant: 20))
    itemView!.addConstraint(NSLayoutConstraint(item: scrollView, attribute: .bottom, relatedBy: .equal, toItem: itemView!, attribute: .bottom, multiplier: 1, constant: 20))

}

【讨论】:

    猜你喜欢
    • 2016-02-04
    • 2015-04-06
    • 2020-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-06
    • 1970-01-01
    相关资源
    最近更新 更多