我正在尝试创建一个包含 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 。
诀窍是您需要在内容 View 中布置您的 B View ,以便您的 nib 文件中只有一个根对象。
这样,当您将内容 View 添加为 View A subview 时,所有约束都将转移(类似于 UITableViewCells 使用其内容 View 的方式)。
重要说明:内容 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/