OK, there are dozens of posts on StackOverflow about this, but none are particularly clear on the solution. I'd like to create a custom UIView
with an accompanying xib file. The requirements are:
UIViewController
– a completely self-contained classMy current approach to doing this is:
Override -(id)initWithFrame:
-(id)initWithFrame:(CGRect)frame {
self = [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class])
owner:self
options:nil] objectAtIndex:0];
self.frame = frame;
return self;
}
Instantiate programmatically using -(id)initWithFrame:
in my view controller
MyCustomView *myCustomView = [[MyCustomView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)];
[self.view insertSubview:myCustomView atIndex:0];
This works fine (although never calling [super init]
and simply setting the object using the contents of the loaded nib seems a bit suspect – there is advice here to add a subview in this case which also works fine). However, I'd like to be able to instantiate the view from the storyboard also. So I can:
UIView
on a parent view in the storyboardMyCustomView
Override -(id)initWithCoder:
– the code I've seen the most often fits a pattern such as the following:
-(id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self initializeSubviews];
}
return self;
}
-(id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self initializeSubviews];
}
return self;
}
-(void)initializeSubviews {
typeof(view) view = [[[NSBundle mainBundle]
loadNibNamed:NSStringFromClass([self class])
owner:self
options:nil] objectAtIndex:0];
[self addSubview:view];
}
Of course, this doesn't work, as whether I use the approach above, or whether I instantiate programatically, both end up recursively calling -(id)initWithCoder:
upon entering -(void)initializeSubviews
and loading the nib from file.
Several other SO questions deal with this such as here, here, here and here. However, none of the answers given satisfactorily fixes the problem:
Could anyone give advice on how to resolve this problem, and get working outlets in a custom UIView
with minimum fuss/no thin controller wrapper? Or is there an alternative, cleaner way of doing things with minimum boilerplate code?
Note that this QA (like many) is really just of historic interest.
Nowadays For years and years now in iOS everything's just a container view. Full tutorial here
(Indeed Apple finally added Storyboard References, some time ago now, making it far easier.)
Here's a typical storyboard with container views everywhere. Everything's a container view. It's just how you make apps.
(As a curiosity, KenC's answer shows exactly how, it used to be done to load an xib to a kind of wrapper view, since you can't really "assign to self".)