swift - 以编程方式将 UIView 的大小调整为 UIViewController 的 View

标签 swift storyboard uikit autolayout

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

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)
    }

}

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

enter image description here

如何使用 AutoLayout 使我的 subview 适应整个 UIView

最佳答案

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

  1. 在 Xcode 6 中,如果您不在 IB 中添加约束,它会为您创建约束。选择红色或蓝色 View ,然后转到尺寸检查器 选项+命令+5。在“约束”下,如果您没有定义任何约束,它可能会报告以下内容:

    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.

    不过,Xcode 5 不会为您添加这些约束。

  3. 如果您决定以编程方式为您不是以编程方式创建的 View 添加约束,则在 Xcode 6 中您应该向 View 添加您自己的约束(例如,“重置为建议的约束”选项,如果您希望它为你创建一个完整的集合)在 IB 中:

    enter image description here

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

    enter image description here

  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))
    }
    

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

    enter image description here

  6. 如果您想诊断您的约束,您可以运行该应用程序,然后单击查看调试器:

    enter image description here

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

    po [[UIWindow keyWindow] _autolayoutTrace]
    

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

关于swift - 以编程方式将 UIView 的大小调整为 UIViewController 的 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28521590/

相关文章:

swift - 从另一个 bundle 加载一个 spritekit 场景?

iOS 10 Swift 和定义 UI 的最佳实践

ios - UINavigationController 在呈现 ViewController 时不执行completionBlocks

ios - 如何使用“确定”警报按钮删除重复的联系人?

ios - removeFromSuperview() 并不总是有效

ios - 在 Firebase 数据库中搜索两个条件

ios - 为什么 touchesForView : returns only 1 touch?

ios - Storyboard UITableView 不显示静态内容

iphone - 如何制作具有左推效果的自定义转场?

ios - 下拉UIScrollView并保持y位置