Shefy Gur-ary
Shefy Gur-ary

Reputation: 658

Instantiate UIView from nib causes infinite loop issue

I'm trying to use a custom view I created.

I use instantiation from nib, but it causes an infinite loop which I'm not sure how to fix. Any idea?

Here is the image of the run result:

enter image description here

And here's the code that causes the issue:

// MARK:  - Init & Setup
// Needed for IBDesignable



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

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

func setup(){
    view = loadViewFromNib()
    view.frame = bounds
    view.autoresizingMask = UIViewAutoresizing(rawValue: UIViewAutoresizing.RawValue(UInt8(UIViewAutoresizing.flexibleWidth.rawValue) | UInt8(UIViewAutoresizing.flexibleHeight.rawValue)))
    addSubview(view)
}

func loadViewFromNib() -> UIView{
    let bundle = Bundle(for:type(of: self))
    let nib = UINib(nibName: "LoginView", bundle: bundle)         // TEST: changin bundle from bundle-> nil

    let view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView
    return view
}

Edit: Here's an image of the connection

enter image description here

Thanks :)

Upvotes: 4

Views: 835

Answers (3)

Dania Delbani
Dania Delbani

Reputation: 826

Quick answer: Since the top-level view in the Xib had its custom class set to YourCustomeView, the xib loading process loadViewFromNib will then call your initWithCoder method again ⛔️🚫♽.

Quick fix: In the Xib, instead of setting the custom class of the view as YourCustomeView, set YourCustomeView as The File Owner of the Xib.

More info https://medium.com/@anandin02/loading-custom-views-in-ios-the-right-way-bedfc06a4fbd

Upvotes: 7

M3nd3z
M3nd3z

Reputation: 316

For anyone having this issue, if you register a Nib for a table or collection view, you are telling that parent view to go and load a nib named 'x' whenever it needs to dequeue a cell.

Normally with Nib code, you'll want a method to go and load the actual XML that makes your layout to tie it to the Nib class, but when you register a reusable view, your registration means that the parent view is responsible for doing this. It will literally go and load an XML file for you and try and tie that to a class when you cast it. By adding another loadNib call inside of this will then cause an infinite loop to happen.

All you need to do is set the cell Nib's class to your custom class, register it and it will do the rest for you with reusable cells - remove the loadNib method from any initialisers inside your cell and add registration code on the collection or table view class.

Upvotes: 0

nagyf
nagyf

Reputation: 869

It is not clear from your example (please next time provide the whole file, not just parts of it), but it looks like you are trying to instantiate LoginView from itself.

init() -> setup() -> loadViewFromNib() -> init() -> ...

The problem is that the instantiate will call the LoginView's init() method, which will again call loadViewFromNib(). I hope you see the problem now.

What are you trying to do with loadViewFromNib?

Edit: In the top right corner of your second image there is a "Custom class" section. There, in the "class" field you have to provide the name of your controller (LoginViewController or something like that). This way you connect your view and controller, and you don't need that custom loadViewFromNib method that causes your problem.

Upvotes: 1

Related Questions