以编程方式将 UIView 的大小调整为 UIViewController 的视图

Size UIView to UIViewController's view programmatically

我正在尝试将 UIView 的大小调整到它的父视图。这有效,但在故事板中自动给出的视图除外。所以这段代码适用于 subview2subview 的大小不适合其封闭视图。

import UIKit

extension UIView {
    func addConstraintsWithVFL(constraintsVFL: String, views: [String: UIView], metrics: [NSObject: AnyObject]? = nil, options: NSLayoutFormatOptions = NSLayoutFormatOptions.allZeros) {
        let mutableDict = (views as NSDictionary).mutableCopy() as NSMutableDictionary
        let constraints = NSLayoutConstraint.constraintsWithVisualFormat(constraintsVFL, options: options, metrics: metrics, views: mutableDict)
        self.addConstraints(constraints)
    }
}

class ViewController: UIViewController {

    @IBOutlet var subview : UIView!  // red, inside self.view
    @IBOutlet var subview2 : UIView! // blue, inside subview

    override func viewDidLoad() {
        super.viewDidLoad()
        var views : [String: UIView]
        views  = ["box": self.subview]//, "super": self.view]
        self.view.addConstraintsWithVFL("V:|-5-[box]-5-|", views: views)
        self.view.addConstraintsWithVFL("H:|-5-[box]-5-|", views: views)
        views  = ["box": self.subview2, "super": self.subview]
        self.view.addConstraintsWithVFL("V:|-5-[box]-5-|", views: views)
        self.view.addConstraintsWithVFL("H:|-5-[box]-5-|", views: views)
    }

}

故事板在任何地方都没有任何限制。结果如下所示:

如何使用 AutoLayout 使我的子视图的大小适合整个 UIView

通常,在 IB 中添加视图时,在 IB 中添加约束也更容易。这样您就不必处理我将在下面列举的所有问题。但是,如果您决定在 IB 中创建视图但以编程方式添加约束,您应该注意:

  1. 在Xcode 6、如果你不在IB中添加约束,它会为你创建约束。 Select 红色或蓝色视图然后转到尺寸检查器 option+command+5.在 "Constraints" 下,如果您没有定义任何约束,它可能会报告以下内容:

    The selected views have no constraints. At build time, explicit left, top, width, and height constraints will be generated for the view.

  2. 如果让 Xcode 在以编程方式添加的约束之外添加这些约束,在 Xcode 6 及更高版本中,您会看到如下警告:

    2015-02-14 21:44:59.766 AutoLayoutTest[22382:8773715] Unable to simultaneously satisfy constraints.

    Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)

    ( 
        "<NSIBPrototypingLayoutConstraint:0x7ff5a9c94770 'IB auto generated at build time for view with fixed frame' H:|-(0)-[UIView:0x7ff5a9c926c0](LTR)   (Names: '|':UIView:0x7ff5a9c93360 )>",
        "<NSLayoutConstraint:0x7ff5a9c99400 H:|-(5)-[UIView:0x7ff5a9c926c0]   (Names: '|':UIView:0x7ff5a9c93360 )>"
    )
    

    Will attempt to recover by breaking constraint

    Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger. The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in may also be helpful.

    Xcode5,虽然,不会为你添加这些约束。

  3. 如果您决定以编程方式为您不是以编程方式创建的视图添加约束,在 Xcode6 中,您应该向视图添加您自己的约束(例如 "Reset to suggested constraints" 选项,如果你想让它为你创建一个完整的集合)在 IB:

    然后检查所有单独的约束并将它们标记为在构建时删除:

  4. 或者,如果您想在添加自己的约束之前以编程方式删除 IB 生成的约束,您可以执行以下操作:

    removeConstraintsBetweenFirstItem(view, secondItem: redView)
    removeConstraintsBetweenFirstItem(redView, secondItem: blueView)
    

    在哪里

    func removeConstraintsBetweenFirstItem(firstItem: UIView, secondItem: UIView) {
        let constraintsToRemove = firstItem.constraints().filter() { (constraint) -> (Bool) in
            if constraint.firstItem as UIView == secondItem {  // in Swift 1.2, use as!
                return true
            }
            if let constraintSecondItem = constraint.secondItem as? UIView {
                return constraintSecondItem == secondItem
            }
            return false
        }
        firstItem.removeConstraints(constraintsToRemove)
    }
    

    这比仅执行以下操作更安全,后者比我更喜欢:

    view.removeConstraints(view.constraints())
    redView.removeConstraints(redView.constraints())
    
  5. 完成后,您现在可以按照您的概述以编程方式添加约束:

    @IBOutlet weak var redView: UIView!
    @IBOutlet weak var blueView: UIView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        let views = ["redView" : redView, "blueView" : blueView]
        view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-5-[redView]-5-|", options: nil, metrics: nil, views: views))
        view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-5-[redView]-5-|", options: nil, metrics: nil, views: views))
        redView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-5-[blueView]-5-|", options: nil, metrics: nil, views: views))
        redView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-5-[blueView]-5-|", options: nil, metrics: nil, views: views))
    }
    

    这会产生以下结果,没有任何不良警告:

  6. 如果你想诊断你的约束,你可以运行应用然后点击查看调试器:

    或者,您可以暂停应用程序的执行并在 (lldb) 提示符下输入

    po [[UIWindow keyWindow] _autolayoutTrace]
    

    通过这些技术中的任何一种,您都可以诊断已添加到视图中的约束。