使用自动布局约束将子类UIView添加到Nib

Nic*_*Liu 5 iphone interface-builder ios autolayout

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

视图B使用Autolayout约束进行设置,并在Interface Builder中进行,包括约束.在viewController的Nib中添加了A.

B - UIImageView(前导= 10,尾随= 10,AlignVertically) - UITextField(前导= 10,尾随= 10,AlignVertically)

ViewController A(300x300,AlignHorizo​​ntally,AlignVertically)

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

加载View BI时,使用以下代码加载其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
}
Run Code Online (Sandbox Code Playgroud)

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

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.
Run Code Online (Sandbox Code Playgroud)

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

NSBundle.mainBundle().loadNibNamed("B", owner: self, options: nil)
self.addSubview(self.viewOfB);
Run Code Online (Sandbox Code Playgroud)

结果是视图被添加到viewController,但它没有采用任何来自其自己的Nib的AutoLayoutConstraints.

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

PS:View A过去也是定制的.

PPS:我使用Swift来做这件事,但我确信Objective-C中的解决方案也可以.

Bog*_*Onu 5

首先,你得到的错误是因为

  • 您无法在视图之间交换或移动约束
  • 在添加新约束之前,必须已在层次结构中添加视图
  • 约束通常添加在包含视图(或共同祖先)的父视图上.

    (有关详细信息,请参阅AutoLayout指南)

我建议让视图A(CustomView:UIView)从nib文件加载内容(B视图)并将它们作为子视图添加.

使用CustomView A的主视图

诀窍是你需要在内容视图中布局B 视图,这样你的nib文件中只有一个根对象.

这样,当您将内容视图添加为视图A子视图时,所有约束都将转移(类似于UITableViewCells如何使用其contentView).

ContentView xib

重要提示:内容视图应该为类类型CustomView的.如果要拖动出口和操作,只需声明CustomView类的File's Owner对象并将其链接到那里.

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

MainView (ViewController's view)
  View A
    Content View
      B1 View
      B2 View
Run Code Online (Sandbox Code Playgroud)

这样,视图A在ViewController的storyboard/xib中配置了它的布局,并且B视图将使用与内容视图相关的nib文件中的约束.

因此唯一要做的就是确保内容视图与视图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()
}

}
Run Code Online (Sandbox Code Playgroud)


rin*_*aro 4

问题是:constraints检索自self正在引用self

相反,您必须引用相同的其他属性并使用相同的其他属性制定新的view约束。像这样:

NSMutableArray *constraints = [NSMutableArray array];
for(NSLayoutConstraint *constraint in self.constraints) {
    id firstItem = constraint.firstItem;
    id secondItem = constraint.secondItem;
    if(firstItem == self) firstItem = view;
    if(secondItem == self) secondItem = view;
    [constraints addObject:[NSLayoutConstraint constraintWithItem:firstItem
                                                        attribute:constraint.firstAttribute
                                                        relatedBy:constraint.relation
                                                           toItem:secondItem
                                                        attribute:constraint.secondAttribute
                                                       multiplier:constraint.multiplier
                                                         constant:constraint.constant]];
}

/* if you also have to move subviews into `view`.
for(UIView *subview in self.subviews) {
    [view addSubview:subview];
}
*/

[view addConstraints:constraints];
Run Code Online (Sandbox Code Playgroud)

而且,我认为您应该从 中复制更多属性self

view.frame = self.frame;
view.autoresizingMask = self.autoresizingMask;
view.translatesAutoresizingMaskIntoConstraints = self.translatesAutoresizingMaskIntoConstraints;
Run Code Online (Sandbox Code Playgroud)

抱歉,Obj-C 代码,我是从这个答案复制的:)