在情节提要中加载xib视图。为什么我们必须要做self.addSubview(nibView)?

时间:2018-07-27 10:16:07

标签: ios swift storyboard xib

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    guard let view = loadViewFromNib() else { return }
    view.frame = self.bounds
    self.addSubview(view) // My question
}

func loadViewFromNib() -> UIView? {
    let bundle = Bundle(for: type(of: self))
    let nib = UINib(nibName: self.className, bundle: bundle)
    return nib.instantiate(withOwner: self, options: nil).first as? UIView
}

我想要customXibView开头为笔尖。看起来像self = loadViewFromNib(),而不是self.addSubview(nibView)。

我发现许多答案都是self.addSubview(nibView)完成的。实际上,看看我们的视图层次结构,我们会发现一个额外的视图。 This is my view hierarchy

有没有办法将xib实例化到情节提要,而不是通过self.addSubview(nibView)。

如果您不明白我的问题,请看Custom UIView from Xib - requirements, good practices。我希望有人能帮助我。

3 个答案:

答案 0 :(得分:0)

有三种情况:

  1. 您拥有CustomView类,其所有UI均已定义 以编程方式使用其drawRect方法。

  2. 您有CustomView类,其UI在情节提要场景的子视图中定义,其类设置为'CustomView'。

  3. 您有CustomView类,其UI在单独的xib中定义。

现在,如果要将CustomView作为子视图包含在viewcontroller中,则该方法会有所不同,具体取决于第一个实例中类的定义方式。其次,您想如何将其包含在ViewController中。

在方案1中添加CustomView:

在viewDidLoad方法中初始化CustomView实例,并将其作为子视图添加到ViewController的视图中。

添加条件2的CustomView:

在这种情况下,您无需执行任何操作。故事板将为您初始化课程。您可以在初始化视图时调用的init(coder)方法中进行其他设置。

添加条件3的CustomView

使用xib初始化视图的正确方法是通过UINib的inistantiateWithOwner方法以编程方式对其进行初始化。然后,在viewcontroller的viewDidLoad方法中将该视图添加为子视图。

您正在执行的操作(或者我可以看到图像的层次结构)是您已将UIView的类更改为自定义类。现在,由于您有单独的xib,因此可以用init(coder)方法对其进行初始化,并将其作为子视图添加到在情节提要中定义和初始化的视图的子视图。因此,您最终将获得额外的容器视图。

如果您不想要额外的视图,请以编程方式添加自定义视图。

OR

(如果可能的话)复制xib中定义的视图并将其放置在viewcontroller扩展坞中,然后将该视图与插座链接并以viewDidLoad方法添加。

答案 1 :(得分:0)

这是您一直想要的答案。您可以只创建CustomView类,并将其主实例包含在带有所有子视图和出口的xib中。然后,您可以将该类应用于情节提要或其他xib中的任何实例。

无需摆弄File的所有者,也无需将插座连接到代理服务器或以特殊方式修改xib,也无需将自定义视图的实例添加为其自身的子视图(即无需self.addSubview(view),这是你的问题。

只需执行以下操作:

  1. 导入BFWControls框​​架
  2. 将您的超类从UIView更改为NibView(或从UITableViewCell更改为NibTableViewCell

就是这样!

它甚至可以与IBDesignable一起使用,以在设计时在情节提要中引用您的自定义视图(包括来自xib的子视图)。

您可以在此处了解更多信息: https://medium.com/build-an-app-like-lego/embed-a-xib-in-a-storyboard-953edf274155

您可以在此处获得开源的BFWControls框​​架: https://github.com/BareFeetWare/BFWControls

以下是驱动它的NibReplaceable代码的简单摘录,以防您好奇:https://gist.github.com/barefeettom/f48f6569100415e0ef1fd530ca39f5b4

汤姆

答案 2 :(得分:-1)

不必将xib视图添加为子视图。考虑一下用法,据我了解,有两种情况

假设您有一个名为customXibView类的视图及其xib,现在在xib中选择该视图,然后从右侧面板中选择[Identity inspector]选项并在[custom class]下默认检查其类为UIView。因此,您可以像现在一样将其保留为UIView并将文件所有者设置为customXibView并从xib作为UIView实例从xib加载。因此,现在的问题是,如果手动或在其他xib中分配customXibView对象,它将如何显示视图xib中的自定义组件。因此,在这种情况下,在您的customXibView's init方法中,您必须加载UIView xib并将其添加到customXibView对象的视图中。

另一种情况,您可以在调用以下方法时将xib的视图[custom class]设置为类customXibView

func loadViewFromNib() -> customXibView? {
    let bundle = Bundle(for: type(of: self))
    let nib = UINib(nibName: self.className, bundle: bundle)
    return nib.instantiate(withOwner: self, options: nil).first as? customXibView
}

您直接获得了加载了UI的customXibView对象,无需将其添加到任何其他视图。但是在这种情况下,如果您分配customXibView类对象,那么如果您不执行当前操作,则不会加载UI。如有疑问,请评论。