ios - 将子类 UIView 添加到具有自动布局约束的 Nib

标签 ios iphone interface-builder autolayout

我正在尝试创建一个包含 2 个自定义 View (B) 的 UIView(A)

View B 是使用自动布局约束设置的,并在 Interface Builder 中制作,包括约束。在viewController的Nib中添加了一个

乙 - UIImageView(前导 = 10,尾随 = 10,AlignVertically) - UITextField(Leading = 10, Trailing = 10, AlignVertically)

View Controller A(300x300, 水平对齐, 垂直对齐)

在 ViewController 中,我将 A 固定为 300x300 并且 B1 和 B2 的前导、尾随、顶部和底部固定为 0。(这应该使 B1 和 B2 为 300x150,如果我遗漏了什么请原谅我)

加载 View B 时,我使用以下代码加载其 Nib:

override func awakeAfterUsingCoder(aDecoder: NSCoder!) -> AnyObject! {
    if self.subviews.count == 0 {
        let bundle = NSBundle(forClass: self.dynamicType)
        var view = bundle.loadNibNamed("B", owner: nil, options: nil)[0] as B
        view.setTranslatesAutoresizingMaskIntoConstraints(false)
        let constraints = self.constraints()
        self.removeConstraints(constraints)
        view.addConstraints(constraints)
        return view
    }
    return self
}

但是当我尝试运行它时,我收到以下警告,包括崩溃:

The view hierarchy is not prepared for the constraint: <NSLayoutConstraint:0x7f897ad1acc0 V:[TestProject.B:0x7f897af73840(300)]>
When added to a view, the constraint's items must be descendants of that view (or the view itself). This will crash if the constraint needs to be resolved before the view hierarchy is assembled. Break on -[UIView _viewHierarchyUnpreparedForConstraint:] to debug.

我还尝试将 View 添加为 View B 的属性,并使用以下代码将其添加到 B

NSBundle.mainBundle().loadNibNamed("B", owner: self, options: nil)
self.addSubview(self.viewOfB);

结果是 View 被添加到 viewController,但它没有从它自己的 Nib 中采用任何 AutoLayoutConstraints。

现在我不知道如何将这个 View 添加到 viewController 的 View 中,包括约束。我究竟做错了什么?有更好的方法吗?

PS:View A 曾经也是自定义的。

PPS:我正在使用 Swift 来执行此操作,但我确信 Objective-C 中的解决方案也能正常工作。

最佳答案

首先你得到的错误是因为

  • 您不能在 View 之间交换或移动约束
  • 在添加新约束之前, View 必须已经添加到层次结构中
  • 约束通常添加到包含 View (或共同祖先)的父 View 上。

    (有关更多详细信息,请参阅 AutoLayout Guide)

我建议让 View A(CustomView:UIView)从 nib 文件加载内容(B View )并将它们添加为它的 subview 。

Main View with CustomView A

诀窍是您需要在内容 View 中布置您的 B View ,以便您的 nib 文件中只有一个根对象。

这样,当您将内容 View 添加为 View A subview 时,所有约束都将转移(类似于 UITableViewCells 使用其内容 View 的方式)。

ContentView xib

重要说明:内容 View 应该属于类类型 CustomView。如果您想拖动导出和操作,只需声明 CustomView 类的 File's Owner 对象并将它们链接到那里。

您的最终 View 层次结构应如下所示:

MainView (ViewController's view)
  View A
    Content View
      B1 View
      B2 View

这样, View A 在 ViewController 的 Storyboard/xib 中配置了布局,您的 View B 将使用与内容 View 相关的 nib 文件中的约束。

所以唯一要做的就是确保内容 View 始终与 View A 具有相同的大小。

class CustomView: UIView
{
 @IBOutlet var _b1Label: UILabel!
 @IBOutlet var _b2Button: UIButton!

func loadContentView()
{
    let contentNib = UINib(nibName: "CustomView", bundle: nil)

    if let contentView = contentNib.instantiateWithOwner(self, options: nil).first as? UIView
    {
        self.addSubview(contentView)

        //  We could use autoresizing or manually setting some constraints here for the content view
        contentView.translatesAutoresizingMaskIntoConstraints = true
        contentView.autoresizingMask = [.FlexibleHeight, .FlexibleWidth]
        contentView.frame = self.bounds
    }
}

override init(frame: CGRect)
{
    super.init(frame: frame)

    loadContentView()
}

required init(coder aDecoder: NSCoder)
{
    super.init(coder: aDecoder);

    loadContentView()
}

}

关于ios - 将子类 UIView 添加到具有自动布局约束的 Nib,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25960081/

相关文章:

ios - 将图像裁剪成 CGRect 总是从 x :0 and y:0 开始

ios - CollectionView prepareForSegue 不将图像数据发送到 DetailView

ios - 收藏 View 动画

iphone - SecCertificateRef : How to get the certificate information?

ios - swift 3 : Swipe to 'Flag' , 如何

iphone - MonoDevelop - 如何从编译中查看 stderr?

ios - 如何使用 AppleScript 删除 plist 键

ios - 从 xib 文件中为对象创建导出

ios - 查找键值编码路径

interface-builder - Xcode Interface Builder 9.1 Collection View Cells 太小 "expected height"