Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where to initialize custom UIView, instantiated in Interface Builder?

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?

like image 984
Rits Avatar asked Jan 02 '11 16:01

Rits


People also ask

How do I create a custom view in swift 5?

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.


3 Answers

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.

like image 65
nacho4d Avatar answered Oct 18 '22 13:10

nacho4d


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:.

like image 27
mplappert Avatar answered Oct 18 '22 12:10

mplappert


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

like image 1
Stephen J Avatar answered Oct 18 '22 13:10

Stephen J