3

I'm trying to instantiate a xib from storyboard but I'm getting an infinite loop. I have seen this snippet working on a video but I'm probably doing something wrong. I can understand why, but not how to make it work... Txs for help ! )

override init(frame: CGRect) {
    super.init(frame: frame)
    setup()
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    setup()
}

func setup()
{
    print("INFINITE LOOP :(")

    self.view = self.loadViewFromNib()
    self.view.frame = bounds
    self.addSubview(self.view)

}

func loadViewFromNib() -> UIView
{
    let nib: UINib = UINib(nibName: "ItemView", bundle: .main)
    let view: UIView = nib.instantiate(withOwner: self, options: nil)[0] as! UIView

    return view
}
Hiromi
  • 209
  • 1
  • 3
  • 12

3 Answers3

3

On Interface Builder, where defined your view, you should set the File Owner's custom class to ItemView (or to other classes you are creating). Do not set the view class.

Unfortunately, StackOverflow won't let me post images, but see the screenshots below.

View with no class

File owner's class

emilrb
  • 129
  • 3
  • Yes exact ! Thanks a lot ! – Hiromi Jul 02 '19 at 00:51
  • This is misleading. The class of the File’s Owner is irrelevant in this situation. – matt Jul 02 '19 at 19:48
  • The File's Owner references the outlets and receives actions. Usually, it's not the same class/instance as the view, (i.e. a view controller and its corresponding view). But it's not [uncommon](https://stackoverflow.com/questions/4763519/loaded-nib-but-the-view-outlet-was-not-set?rq=1) for custom views to be structured that way. – emilrb Jul 03 '19 at 14:38
0

You have not shown enough code, but it looks like you're effectively doing this (I've simplified your code to focus on the problem):

class ItemView : UIView {
    // called when an ItemView is loaded from a nib
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        loadViewFromNib()
    }
    // called to load an ItemView from a nib
    func loadViewFromNib(){
        let nib: UINib = UINib(nibName: "ItemView", bundle: .main)
        let view: UIView = nib.instantiate(withOwner: self, options: nil)[0] as! UIView
    }
}

So it seems this view is an ItemView loaded from a nib, and as it is loaded it tries to load another ItemView from a nib, which tries to load another ItemView from a nib....

A view cannot load itself from a nib like that. You need to put all that code in the class of some other view that will act as the ItemView's superview.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • Yep nib.instantiate() calls init that calls loadViewFromNib() etc... I have no problem when creating the view by code. – Hiromi Jul 01 '19 at 23:35
  • So what is the right way to implement init when using the storyboard ? – Hiromi Jul 01 '19 at 23:36
  • I don't know what you are trying to do. I can only explain why this way is circular. – matt Jul 01 '19 at 23:36
  • I just want to instantiate this exact custom view from the story board (dragging a uiview on the storyboard and making its class an 'ItemView')... I'm new at swift pardon me just being an Android developer :) – Hiromi Jul 01 '19 at 23:40
  • But this exact custom view is already configured in a _nib_ (a _.xib_ file). It makes no sense to stick it in the storyboard and then say you want it to come from the nib. Pick one. – matt Jul 01 '19 at 23:54
  • Yes it does. You can create your custom view using a xib and use it from the storyboard. Anyway thanks for your help – Hiromi Jul 02 '19 at 00:54
  • No. You didn't read what I said. My answer tells you that your mistake is that the view in the storyboard is the _same_ class as the view in the nib. And that's why you get an infinite loop. My answer says that you need the view in the storyboard to be a _different_ class from the view in the nib. – matt Jul 02 '19 at 12:17
0

Found! This can be helpfull for some people

I was setting the view class instead of the "owner" of the xib file! So the xib was creating the view that was loading the xib and so on...

Thanks to @RealNmae on the link: How do I create a custom iOS view class and instantiate multiple copies of it (in IB)?

Hiromi
  • 209
  • 1
  • 3
  • 12
  • That is exactly what my answer said. The class of the view you load must not be the class of this view, or we get a loop. The stuff about the File’s Owner is irrelevant. – matt Jul 02 '19 at 20:00