使用自动布局约束将子类UIView添加到Nib [英] Adding a subclassed UIView to a Nib with its auto layout constraints

查看:182
本文介绍了使用自动布局约束将子类UIView添加到Nib的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to create a UIView(A) containing 2 custom Views (B) in it

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

View B is setup using Autolayout Constraints and made in Interface Builder, including the constraints. A is added in the Nib of the viewController

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

B - UIImageView(Leading = 10, Trailing = 10, AlignVertically) - UITextField(Leading = 10, Trailing = 10, AlignVertically)

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

ViewController A(300x300, AlignHorizontally, AlignVertically)

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

In the ViewController I have A to be fixed at 300x300 and B1 and B2 has its Leading, Trailing, Top and Bottom pinned at 0. (which should make B1 and B2 to be 300x150, forgive me if I miss something out)

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

When loading View B I use the following code to load its 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
}

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

But when I try to run this I get the following warning including a crash:

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 B的属性并使用以下代码添加它到B

I have also tried adding the view as a property of View B and use the following code to add it to B

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

这样的结果是视图被添加到viewController,但它没有采用任何一个来自它自己的Nib的AutoLayoutConstraints。

the result of this is the view is added to the viewController, but it is not adopting any of the AutoLayoutConstraints from its own Nib.

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

Right now I have no idea how to add this view to the viewController's view including the constraints. What am I doing wrong? Is there a better way to do this?

PS:查看A过去也是自定义的。

PS: View A used to be custom too.

PPS :我使用Swift来做这件事,但我确信Objective-C中的解决方案也能正常工作。

PPS: I am using Swift to do this, but I'm sure solutions in Objective-C works as well.

推荐答案

你得到的所有错误是因为

First of all the error you are getting is because


  • 你不能在你的观点之间交换或移动约束

  • 在添加新约束之前必须已在层次结构中添加视图

  • 通常会在包含视图(或共同祖先)的父视图上添加约束。

  • you can't swap or move constraints between your views
  • the views must already be added in the hierarchy before adding new constraints
  • the constraints are usually added on the parent view that holds the views (or common ancestor).

(有关详细信息,请参阅自动布局指南

(for more details see AutoLayout Guide)

我建议查看A (CustomView:UIView)从nib文件加载内容(B视图)并将其添加为子视图。

I would suggest having view A (CustomView : UIView) loading the contents (B Views) from the nib file and adding them as it's subviews.

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

The trick is that you need to layout you B views inside a content view so that your nib file has only one root object in it.

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

This way, when you add the content view as the view A subview, all constraints will transfer over(similar with how UITableViewCells use their contentView).

重要提示:内容视图应 NOT 属于类型CustomView。如果要拖动出口和操作,只需声明CustomView类的文件所有者对象并将其链接到那里。

Important Note: The content view should NOT be of the class type CustomView. If you want to drag outlets and actions just declare the File's Owner object of the class CustomView and link them there.

您的最终视图层次结构应该看起来像这样:

Your final view hierarchy should look like this:

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

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

This way view A has it's layout configured in the ViewController's storyboard/xib and you B views will use the constraints from the nib file related to the content view.

所以唯一可以确保内容视图与视图A的大小始终相同。

So the only thing let is to make sure is that the content view will always have the same size with 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()
}

}

这篇关于使用自动布局约束将子类UIView添加到Nib的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆