Hiromi
Hiromi

Reputation: 229

Infinite loop on instantiated view from xib on storyboard

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
}

Upvotes: 3

Views: 594

Answers (3)

Hiromi
Hiromi

Reputation: 229

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)?

Upvotes: 0

emilrb
emilrb

Reputation: 139

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

Upvotes: 3

matt
matt

Reputation: 535121

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.

Upvotes: 0

Related Questions