简体   繁体   中英

UIView init with coder causes a recursion

I am trying to embed a UIView I've prepared, which is located in a xib file, to a storyboard.

What I've done so far is:

class TestUIView : UIView {
    @IBOutlet weak private var firstButton: UIButton!
    @IBOutlet weak private var secondButton: UIButton!

    // MARK - Lifetime

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

        let view = NSBundle.mainBundle().loadNibNamed("TestUIView", owner: self, options: nil).first as! TestUIView

        self.addSubview(view)
    }
}

But for some reason I get bad access memory exception. From looking into stack trace I see a whole bunch of calls to initWithCoder http://i.stack.imgur.com/iH6Am.png I'm not sure why NSBundle.mainBundle().loadNibNamed causes this, any ideas?

Turn's out what I have done wrong is how I prepared the .xib file, I've set the View itself, instead of the file owner to TestUIView class. After changing the file owner(and reseting the constraints), everything worked fine.

For future seekers....

Brief : The recursive call of required init?(coder aDecoder: NSCoder) occurs when you accidentally set your custom view class in identity inspector of your ContentView.

When the compiler tries to load your Nib file(the owner view) it first needs to initiate your ContentView (see the following picture) and if you have mistakenly set the custom class for your ContentView or any of its subviews, it goes through another Nib loading process and stuck in a recursive infinite loop.

To do it the right way, you should only set your custom view class for the view in Placeholder's part. Please see 1 and 2 in the following picture.

In this picture I have defined a custom class named CardView .

在此处输入图片说明

You just defined the way to build a TestUIView that contains a TestUIView that contains a TestUIView that contains a TestUIView ...

Your don't have to call

let view = NSBundle.mainBundle().loadNibNamed("TestUIView", owner: self, options: nil).first as! TestUIView

from

init?(coder aDecoder: NSCoder)

This way you are creating an infinite loop because loadNibNamed will automatically call the init?(coder aDecoder: NSCoder) .

Just remove these lines

let view = NSBundle.mainBundle().loadNibNamed("TestUIView", owner: self, options: nil).first as! TestUIView
self.addSubview(view)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM