美文网首页
iOS xib中使用其它xib

iOS xib中使用其它xib

作者: 今天写明天改 | 来源:发表于2021-11-28 17:12 被阅读0次

    背景

    最近在做需求的时候,遇到了一个事情:某个自定义view的awakeFromNib()函数中爆出了如下错误
    Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
    原因是函数中使用了xib中的一个outlet。于是就有了今天的问题,awakeFromNib()不是在所有对象都解档完毕后才发送的么,走到这里而它的子view还没有初始化是为什么,平时我们自定义view和xib的关联又是怎么回事。带着这些问题我们往下看个例子

    代码使用xib

    要实现自定义view和xib的结合,首先我们要有如下的两个文件


    subView和xib

    如何让这两个文件关联起来呢 我们选中xib的属性面板 然后将view的custom class改为自定义View的类型:


    更改自定义view的类型
    然后我们给自定义view加一个outlet 并在awakeFromNib()中对它做一些配置
    配置Outlet

    之后我们在使用的地方使用如下代码调用

    let owner = SubView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
    let loadedView = Bundle.main.loadNibNamed("SubView", owner: owner, options: nil)?.first as! SubView
    self.view.addSubview(loadedView)
    
    手动加载view的xib

    我们可以看到view的xib已经正确加载了 当然我们也可以传递一个nil的owner给加载函数也能成功,例如

    let loadedView = Bundle.main.loadNibNamed("SubView", owner: nil, options: nil)?.first as! SubView
    self.view.addSubview(loadedView)
    

    xib使用xib

    那么如果我想在xib中使用这个自定义view的xib呢?大家第一想法应该是在使用的xib属性中更改view的class 例如:


    xib中设置其他view的自定义类型

    这个时候我们如果运行就会出现如下错误


    访问子控件失败
    这就是我们开头讲到的问题,让我们先来看看究竟是什么原因导致的。首先看下我们的堆栈
    崩溃堆栈

    从图里可以看到,我们崩溃之前只调用了instantiateWithOwner:options:这个方法用来解档viewController对应的nib文件,之后就给我们对应的自定义view发送了awakefromNib的消息,也就是整个过程中,SubView的xib文件并没有进行解档,而是直接收到解档完成的消息。

    原理

    为什么Subview.xib并没有解档却收到了消息呢,我们还要从xib的解档来说,当我们在父view的xib中将某个view设置为自定义view的类型的时候,会发生什么呢,首先,父view的xib会将这一个view归档到xib中。那么归档的内容是什么呢?
    因为view的其他子view都在subView.xib中,所以父view的xib只会归档这个空的view,所以解码的时候自然subView下边没有任何的子view。
    有人会问了。subview和xib不是已经关联了么。那么加载xib的时候为什么没有加载subview.xib中的内容而是直接崩溃了呢?注意我们之前所说的,当subView收到消息的时候,并不是subView.xib解档完成,而是父xib接档完成发送的消息。所以问题就出现了。

    正确用法

    如何在xib中使用另一个自定义的xib呢
    两个步骤,

    1. 在自定义view中将view和xib的fileOwner关联起来


      关联xib和fileOwner

      2.在自定义view的initWithCoder中加载view的xib

    required init?(coder: NSCoder) {
            super.init(coder: coder)
            Bundle.main.loadNibNamed("SubView", owner: self, options: nil)?.first as! UIView
            self.addSubview(self.view)
    }
    

    这个时候我们就可以开心的使用了

    总结

    大家使用的时候一定要注意各个view和nib和生命周期和使用过程。随意使用就只有崩溃了。要多学习多总结。

    相关文章

      网友评论

          本文标题:iOS xib中使用其它xib

          本文链接:https://www.haomeiwen.com/subject/jgthxrtx.html