I have a subclass of UIView that's instantiated in a XIB file. I need it to do some initialization (settings some variables and creating a subview).
However, I do not always instantiate this view via Interface Builder. I do it programmatically too. In both cases, the initialization needs to be the same.
My designated initializer is initWithValues:
.
The question is; where do I perform the initialization?
Since I have to perform it in 2 different locations, I figured I need to refactor it in a separate initialize
method (or something like that), and call it from initWithValues:
.
But when loading from IB, both initWithCoder:
and awakeFromNib
are called. From which method do I have to call initialize
? Or do I have to call initWithValues:
from initWithCoder:
and do nothing in awakeFromNib
?
Creating Custom Views programatically Open Xcode ▸ File ▸ New ▸ File ▸ Cocoa Touch class ▸ Add your class name ▸ Select UIView or subclass of UIView under Subclass of ▸ Select language ▸ Next ▸ Select target ▸ Create the source file under your project directory.
You should use initWithFrame:
when initializing views (since it's the designated initializer). Hence, if you have initWithValues:
make sure you call initWithFrame:
from it.
Something like this should work for initializing: ;)
- (void)initialize{
//init your ivars here
}
- (id)initWithCoder:(NSCoder *)aCoder{
if(self = [super initWithCoder:aCoder]){
[self initialize];
}
return self;
}
- (id)initWithFrame:(CGRect)rect{
if(self = [super initWithFrame:rect]){
[self initialize];
}
return self;
}
I was going to add a further explanation, but mplappert's answer is clear enough. Use awakeFromNib
if necessary.
That depends on what you need to initialize. As soon as awakeFromNib
gets called, all outlets and action connections of your view are established which is not the case in initWithCoder:
. So if you need to rely on those connections, use awakeFromNib. Otherwise you can safely do all your initializing in initWithCoder:
.
Unfortunately, the above answers don't take into account these things: - (void) awakeAfterUsingCoder - and the fact it's called after anything is created by the coder (once for every Xib view). awakeFromNib suffers from the same fate, I've noticed. (The reason I found this)
Another initializing issue is that initWithCoder and initWithFrame can be avoided for custom views. And if they are called, lazy loading (though not as important on views themselves), means you "might" be able to modify values. I believe I've done so in initWithCoder, but if you then initialize values in awakeFromNib, it's undone at least once.
I've gone so far as to:
- (void) awakeFromNib (or didMoveToSuperView);
{
BOOL called = NO;
if(!called)
{
called = YES;
}
}
Another method I use is to simply call the initializer needed, then call my own class or superclass-specific initializer.
I, too, am looking for a dependable one-time place I can rely on. Until then, I hope my headaches save the next person an hour or so.
Steve
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