I'm developing an iOS 5+ app with latest SDK.
I have created a custom UIView (TopMenuView
) with a custom XIB. On Interface Builder I have changed, on this XIB, UIView
class to TopMenuView
. I haven't set any File's Owner
.
On TopMenuView.m
I have:
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self)
{
NSLog(@"init with coder: %d", counter);
counter++;
// Add custom XIB
NSArray *topMenuView = [[NSBundle mainBundle] loadNibNamed:@"TopMenuView"
owner:nil
options:nil];
UIView *nv = [topMenuView objectAtIndex:0];
[self addSubview:nv];
}
return self;
}
Using Interface Builder I have added a UIView
to a UIViewController
and changed this UIView
class to TopMenuView
.
But, when I run the app, I get this log message 4251 times:
2013-10-13 20:49:34.078 MyProject[470:c07] init with coder: 0
And then, I get an EXC_BAD_ACCESS
here:
NSArray *topMenuView = [[NSBundle mainBundle] loadNibNamed:@"TopMenuView"
owner:nil
options:nil];
The reason it's calling the initWithCoder so many times is due to wrong class setup in your .xib file.
Make sure the Custom Class on the File's Owner is your custom UIView class:
And make sure the class on the root View is the default UIView:
And now this is all you need in your custom class (in Swift):
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
let view = NSBundle.mainBundle().loadNibNamed("TopMenuView", owner: self, options: nil)[0] as! UIView
self.addSubview(view)
view.frame = self.bounds
}
You are most likely getting into an infinite loop because you're recursively calling initWithCoder
. One workaround is to check if your subclass has any subviews first.
-(id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
if (self.subviews.count == 0) {
NSArray *topMenuView = [[NSBundle mainBundle] loadNibNamed:@"TopMenuView" owner:nil options:nil];
UIView *nv = [topMenuView objectAtIndex:0];
[self addSubview:self.view];
}
}
return self;
}
This is how I did it:
//Add Custom View to my main view of viewcontroller
self.customNavView = [[CustomNavigationView alloc] init];
self.customNavView = [[[NSBundle mainBundle] loadNibNamed:@"CustomNavigationView" owner:self options:nil] objectAtIndex:0];
[self.customNavView setFrame:CGRectMake(0, 20, 320, 54)];
[self.view addSubview:self.customNavView];
Here CustomNavigationView is a UIView subclass with Files Owner Class as UIView and the UIView custom class as CustomNavigationView.
This works for me.
Your - (id)initWithCoder:(NSCoder *)aDecoder
is called whenever TopMenuView
is created by loading your xib.
Thus you are recursively calling your initWithCoder:
Comment all your method - (id)initWithCoder:(NSCoder *)aDecoder
and where you want to use TopMenuView
probably in some controller use the below code
NSArray *topMenuView = [[NSBundle mainBundle] loadNibNamed:@"TopMenuView" owner:nil options:nil];
UIView *nv = [topMenuView objectAtIndex:0];
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With