NSLayout 约束失败

Posted

技术标签:

【中文标题】NSLayout 约束失败【英文标题】:NSLayout Constraints failing 【发布时间】:2015-12-15 09:10:34 【问题描述】:

所以我正在尝试使用以下代码以编程方式向我的视图添加约束。我正在尝试将一些 32 的顶部空间和一些 16 的前导空间添加到以编程方式添加到我的一个视图控制器的视图中,但我似乎遇到了一些问题。

下面是我如何将按钮返回到我的视图的示例,以便可以通过编程方式添加它。

// Creating the button
func createDismissButton(vwParentView: OnboardingViewController) -> UIButton 

     let dismissButton = UIButton()
     dismissButton.setImage(UIImage(named: "Close"), forState: .Normal)
     dismissButton.frame =  CGRectMake(16, 32, 34, 34)
     dismissButton.addTarget(self, action: "dismiss:", forControlEvents: .TouchUpInside)

     // AUTO LAYOUT

    // WIDTH & HEIGHT
    let dismissWidthButtonConstraint = NSLayoutConstraint (item: dismissButton,
        attribute: NSLayoutAttribute.Width,
        relatedBy: NSLayoutRelation.Equal,
        toItem: nil,
        attribute: NSLayoutAttribute.NotAnAttribute,
        multiplier: 1,
        constant: 34)

    let dismissHeightButtonConstraint = NSLayoutConstraint (item: dismissButton,
        attribute: NSLayoutAttribute.Width,
        relatedBy: NSLayoutRelation.Equal,
        toItem: nil,
        attribute: NSLayoutAttribute.NotAnAttribute,
        multiplier: 1,
        constant: 34)

    // SPACING
    let dismissButtonTopConstraint = NSLayoutConstraint(item: dismissButton,
        attribute: .Top,
        relatedBy: .Equal,
        toItem: vwParentView.view,
        attribute: .Top,
        multiplier: 1.0,
        constant: 32)

    let dismissButtonLeftConstraint = NSLayoutConstraint(item: dismissButton,
        attribute: .Leading,
        relatedBy: .Equal,
        toItem: vwParentView.view,
        attribute: .Leading,
        multiplier: 1.0,
        constant: 16)


    dismissButton.addConstraint(dismissWidthButtonConstraint)
    dismissButton.addConstraint(dismissHeightButtonConstraint)

    dismissButton.addConstraint(dismissButtonTopConstraint)
    dismissButton.addConstraint(dismissButtonLeftConstraint)

     return dismissButton

但它似乎在我添加vwParentView.view的间距上失败了,因为它在日志中显示了关于 item 属性必须是视图的错误。但是现在当我使用这些属性运行代码时,我得到了以下错误。

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

我正在尝试将此按钮添加到也以编程方式创建的视图中,如下所示。

override func viewWillAppear(animated: Bool) 
    // Add the view below to the current view controller
    self.view.addSubview(generatePurchasePaging().view)


func generatePurchasePaging() -> OnboardingViewController 

    let welcomePage = OnboardingContentViewController(title: "PAY WHAT YOU WANT", body: "I made my app so you could have the best experience reading tech related news. That’s why I want you to value it based on your satisfaction.", image: UIImage(named: "Purchase-Pig"), buttonText: "")  () -> Void in

    

    let firstPurchasePage = OnboardingContentViewController(title: "MINT", body: "The app is great but there’s still a few places in room of improvement. If this is your feeling this is for you.", image: UIImage(named: "Purchase-Mint"), buttonText: "69p")  () -> Void in

    

    let secondPurchasePage = OnboardingContentViewController(title: "SWEET", body: "IThis is the suggested price where you value the time I spent on development and design. Feel free to pay more or less.", image: UIImage(named: "Purchase-Lolly"), buttonText: "£1.49")  () -> Void in

    

    let thirdPurchasePage = OnboardingContentViewController(title: "GOLD", body: "Hello is it me your looking for, if this popped into your mind using the app then this is the price for you.", image: UIImage(named: "Purchase-Coin"), buttonText: "£2.99")  () -> Void in

    

    let purchaseVC = OnboardingViewController(backgroundImage: nil, contents: [welcomePage, firstPurchasePage, secondPurchasePage, thirdPurchasePage])
   purchaseVC.shouldMaskBackground = false

    purchaseVC.view.addSubview(createDismissButton(purchaseVC))
    return purchaseVC

【问题讨论】:

【参考方案1】:

一些想法:

    当您以编程方式创建视图时,translatesAutoresizingMaskIntoConstraints 默认为 true。关闭此功能。

    在将另一个视图(它的父视图?)添加到视图层次结构之前,您正在对其设置约束。所以确保 (a) 你首先执行addSubiew 和 (b) 这个约束应该被添加到最近的公共父级(通常是超级视图),而不是按钮本身。 .NotAnAttribute 约束可以添加到按钮,但其余的应该添加到最近的公共父级。

    您正在设置约束和frame。如果你做前者,则不需要后者。

如果在您解决上述问题后仍然无法正常工作,请分享错误的全文,而不仅仅是单行消息。

【讨论】:

嘿,谢谢你的回复,所以如果我只是设置框架我不需要约束?因为我担心在不同的设备上它会定位不同 要么关闭translatesAutoresizingMaskIntoConstraints 并添加约束,要么保持translatesAutoresizingMaskIntoConstraints 开启并设置frame(以及自动调整大小的掩码)。如今,您通常会选择前者。

以上是关于NSLayout 约束失败的主要内容,如果未能解决你的问题,请参考以下文章

我怎样才能正确地进行非主动/主动约束?

在 Swift 中以编程方式添加约束不起作用

键约束失败 - 这是啥意思?

具有自动布局的 UITableviewCell 约束失败

MySQL 错误 1822:添加外键约束失败;缺少约束索引但索引存在

外键 Laravel 8 foreignId + 约束 - 无法添加或更新子行:外键约束失败