6

In order to re-use a certain subview throughout my application (which is storyboard based), I decided to build the subview as a nib, and load it in. To do this, I have done the following:

I have a UIView subclass we can call Widget. I create a corresponding xib file, set the File owner property to my new subclass, hook up the IBOutlets.

Then, in my storyboard, I have a uiview inside of a view controller, and I set its class to the Widget class I created.

Within the widget class, I override initWithCoder, and in there load the nib as follows:

-(id)initWithCoder:(NSCoder *)aDecoder{
    if ((self = [super initWithCoder:aDecoder])){
        [self addSubview:[[[NSBundle mainBundle] loadNibNamed:@"Widget" owner:self options:nil] objectAtIndex:0]];
    }
    return self;
}

The app would crash at this point, and setting a break point here revealed that initWithCoder was being called over and over again.

It seems like I have mixed two methods for using a nib in this situation, but I'm unclear as to where I went wrong. I can throw up a stack trace if necessary, but it's basically endless nested calls to the same function.

Chris
  • 1,421
  • 1
  • 15
  • 21

2 Answers2

19

Did you happen to set the View's "Custom Class" in your .xib file to "Widget"?

That would explain the behaviour you're seeing, because initWithCoder: is the initializer for all things loaded from a xib:

  1. Your parent view, which contains a Widget object, is loaded from the xib
  2. The Widget's initWithCoder: method gets called, and tries to load the Widget xib
  3. The Widget xib contains a UIView with the Custom Class "Widget", so again, a Widget object is being initialized with initWithCoder:, etc.

If that is indeed the case, all you have to do is remove the "Custom Class" entry for the UIView in your Widget's xib.

Andreas Ley
  • 9,109
  • 1
  • 47
  • 57
  • 1
    but if you remove the Custom Class value it's not possible to use its IBOutlets and IBActions... – nano Feb 25 '15 at 11:04
  • @nano Of course you can use a custom class for your view; you just need to prevent recursion. – Andreas Ley Feb 25 '15 at 12:06
  • whats the best way to prevent recursion without removing "Custom Class" from xib? – Yaro May 31 '15 at 15:35
  • @Jaro Just create an instance of your view with `[[NSBundle mainBundle] loadNibNamed:@"YourNibFileNameWithoutSuffix" owner:self options:nil]`. This will create the `UIView` instance you need. The only thing you *can't* do is create an instance of your view class programmatically and then try to load its own nib in `initWithCoder:` (because that leads to another instance of your view class being created and so on). – Andreas Ley May 31 '15 at 17:03
  • @Andreas: it was my fault, I have set "Custom class" to the main "view" instead of the Parent View Controller. Here we go recursion :) lesson learned.. – Yaro Jun 08 '15 at 15:52
3

I had same problem. My mistake was in empty File's Owner class. In File's Owner custom class must be NOT empty (Widget), and root view must be empty.

IBActions and IBOutlets were fine.

Marriage
  • 501
  • 3
  • 15