There is a common question: "Where should I initialize subviews (programmatically)?". Answer is quite complicated.
What do we need to create an object? Right: allocate memory and initialize object. What does this actually mean?
To initialize - to set
starting values.
So, can you create subviews in one place? Oh, yes you can. But you should
not.
The main factor is view's frame. It could be changed. And it should be set depending on current device orientation.
Q: Ok, where should I create subview and set initial parameters?
A: Let it be Rule #1: Create (allocate and init) subviews at -viewDidLoad. That method is called only once. Obviously, when your view controller was loaded from storyboard or xib.
Here is a simple example:
Firstly, we define our subviews at class extension (looks like a nameless category):
@interface ViewController ()
{
UIView *subviewOne;
UIImageView *imageView;
UILabel *labelForBoldText;
}
@end
Secondly, we create subviews by allocating memory, defining attributes and adding them to main view:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
// Init subviews //
// view
subviewOne = [[UIView alloc] init];
subviewOne.backgroundColor = [UIColor redColor];
subviewOne.layer.cornerRadius = 20.0f;
[self.view addSubview:subviewOne];
// label
labelForBoldText = [[UILabel alloc] init];
labelForBoldText.backgroundColor = [UIColor clearColor];
labelForBoldText.textColor = [UIColor blackColor];
labelForBoldText.font = [UIFont boldSystemFontOfSize:20.0f];
[self.view addSubview:labelForBoldText];
}
Last goal is to set the frame. And here comes the main question:
Q: What place is the best to set the frame?
A: In my opinion, -viewWillLayoutSubviews.
Why do I prefer this method to -viewWillAppear? Apple documentation says: "-viewWillAppear - Called when the view is about to made visible." So, it's used to handle changes in screens. But what if user just flipped device on the other side? -viewWillAppear will not be called. You don't need to think about it if you are using autoLayout, because it will make frame changes depending on constraints.
On the other hand, -viewWillLayoutSubviews will be called when orientation changes will take place and the new view frame is already set. So, you can update your subviews frame just before their -layoutSubview method will be called.
Frame setter code will look like:
- (void)viewWillLayoutSubviews {
// Define frame for view
CGRect viewFrame = CGRectMake(0, 0, 100, 100);
subviewOne.frame = viewFrame;
// Define frame for label
CGRect labelFrame = CGRectMake(0, 100, 100, 20);
labelForBoldText.frame = labelFrame;
}
To conclude, I suggest following steps for creating subviews programmatically:
- Define subviews at class extension to make it accessible
- Initialize subviews and add to view at -viewDidLoad
- Set frames at -viewWillLayoutSubviews
Dismissed.
Contact me at twitter (@ibvene) if you have any questions.