Skip to main content
 首页 » 操作系统

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

2024年01月01日35arxive

我正在尝试将 UIView 的大小调整到它的父 View 。这有效,但在 Storyboard中自动给出的 View 除外。所以这段代码适用于 subview2 但 subview 的大小不适合其封闭 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在任何地方都没有任何限制。结果如下所示:

如何使用 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 中:

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

  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] 
    

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