Reputation: 85975
When I make an object to use in NIB, the object should implement -initWithCoder:
. However I can't figure out regular pattern implementing this.
I have been used this code.
- (id) initWithCoder:(NSCoder *)aDecoder
{
if(self=[super initWithCoder:aDecoder])
{
// initialize my object.
}
return self;
}
But I have to make same code for UIView instantiated by code like this.
- (id) initWithCoder:(NSCoder *)aDecoder
{
if(self=[super initWithCoder:aDecoder])
{
// initialize my object.
}
return self;
}
- (id) initWithFrame:(CGRect)frame
{
if(self=[super initWithFrame:frame])
{
// initialie my obejct.
}
return self;
}
I feels something wrong. Any recommendations?
*Of source the initialization logic can be extracted into a new method, but it's not a point.
Upvotes: 1
Views: 1572
Reputation: 92336
Apart from Jacques answer, which is the correct way to solve this problem, you had a logic error. In your initWithCoder
you have set self = [super initWithCoder:aDecoder];
and then you do return [self init];
. In init
, you again overwrite self through self = [super init];
, potentially reversing things you have done in initWithCoder:
. And again in init
, you have return [self init];
which causes an endless recursion until the stack overflows.
The pattern for init methods is something like this:
- (id) initWithFoo:(Bar *)baz {
if ((self = [super initWithFoo:baz])) {
// Do custom initialization.
}
return self;
}
or:
- (id) initWithFoo:(Bar *)baz {
if ((self = [super initWithSome:baz other:@"signature"])) {
// Do custom initialization.
}
return self;
}
Also, a bit of clarification: - (id) initWithCoder:(NSCoder *)aDecoder
gets called on deserialization. In this case on deserialization done by loading a NIB/XIB. There is a counterpart, - (void)encodeWithCoder:(NSCoder *)encoder
. Read the Archives and Serialization Programming Guide, you might find that useful if you want to store objects on disk or want to transmit them over a network.
Anyway, with NIBs, once they are loaded the awakeFromNib
method is called for each object that is stored inside a NIB and it serves as a kind of second-level-initializer.
Then, there's initWithFrame:
. This is the designated initializer and the one you call when creating UIView instances programmatically.
Upvotes: 1
Reputation: 6040
Use awakeFromNib to initialize a UIView that's being created from a NIB file. If you want to make it general so that it can be created either from a NIB file or programmatically, make a method like configureObject and call it from both the designated initializer (often initWithFrame:) and from awakeFromNib.
- (void)configureObject {
// Do initialization here
}
- (id)initWithFrame:(CGRect)frame {
if(self = [super initWithFrame:frame])
{
[self configureObject];
}
return self;
}
- (void)awakeFromNib {
[self configureObject];
}
Upvotes: 4