Reputation: 2330
In my application I've subclassed UIView and it has three ivars declared in .m file (2UIButton and an UITextField ). I use this object by drag the UIView from the objects library and convert them to my subclass. below is my implementation
@interface Prescriber()<UITextFieldDelegate>
{
UIButton *_addButton;
UIButton *_lessButton;
UITextField *_valueField;
}
@end
@implementation Prescriber
@synthesize value=_value,intValueofStrig=_intValueofStrig;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
NSLog(@"prescriber called");
return self;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
-(void)layoutSubviews
{
if (!_addButton) {
_addButton=[[UIButton alloc]init];
[_addButton addTarget:self action:@selector(addbuttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[_addButton setBackgroundImage:[UIImage imageNamed:@"add1.png"] forState:UIControlStateNormal];
_addButton.layer.cornerRadius=5;
}
if (!_lessButton) {
_lessButton=[[UIButton alloc]init];
[_lessButton addTarget:self action:@selector(lessButoonClicked:) forControlEvents:UIControlEventTouchUpInside];
[_lessButton setBackgroundImage:[UIImage imageNamed:@"Minus.png"] forState:UIControlStateNormal];
}
if (!_valueField) {
_valueField=[[UITextField alloc]init];
_valueField.delegate=self;
}
///positioning the addbutton on left corner and right corner and position and
textfield in the center
}
I've done the configuring code in the -(void)layoutSubviews method as my -initwithFrame not get called as they are already in the xib file. what I want to know is ,Is it right to do our initialization in the -layoutSubViews as there is a chance for this method to get called another time. Or am I able to invoke the -viewDidLoad like delgate method for my subclassed View too?
Edit:- It is possible by creating an IBOutlet but that way is a constraint for me.
Upvotes: 3
Views: 501
Reputation: 104698
For IB instances, you can setup you view and initialize its subviews in -awakeFromNib
:
- (void)awakeFromNib
{
[super awakeFromNib];
// your initialization code here
}
Using this method, your instance is fully initialized and the IB connections have been established. It is also guaranteed to be called exactly once (per instance). If you also create instances of this type programmatically, then you should consider a shared initialization method which can be called in -awakeFromNib
.
The problem with adding subviews in the initializer is that your view is in a partially constructed state, and ultimately there may be side effects or difficulty initializing your view/object graph in a well defined and deterministic manner; -awakeFromNib
at least ensures all NIB objects have been created and the connections exist, although the order in which -awakeFromNib
is called is not defined. If you need exact ordering, then you should really approach it programmatically.
Upvotes: 1
Reputation: 122401
Do it in a private setup method:
@interface MyViewClass ()
- (void)_setup;
@end
@implementation MyViewClass
- (void)_setup
{
_addButton=[[UIButton alloc]init];
[_addButton addTarget:self action:@selector(addbuttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[_addButton setBackgroundImage:[UIImage imageNamed:@"add1.png"] forState:UIControlStateNormal];
_addButton.layer.cornerRadius=5;
_lessButton=[[UIButton alloc]init];
[_lessButton addTarget:self action:@selector(lessButoonClicked:) forControlEvents:UIControlEventTouchUpInside];
[_lessButton setBackgroundImage:[UIImage imageNamed:@"Minus.png"] forState:UIControlStateNormal];
_valueField=[[UITextField alloc]init];
_valueField.delegate=self;
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self != nil)
{
[self _setup];
}
return self;
}
- (id)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self != nil)
{
[self _setup];
}
return self;
}
@end
Upvotes: 2
Reputation: 125007
I've done the configuring code in the -(void)layoutSubviews method as my -initwithFrame not get called
UIView
has two designated initializers. When the view is loaded from a nib, -initWithCoder:
is called instead of -initWithFrame:
. You can put initialization code in that method, or put it in a common initialization method that you call from both initializers.
Is it right to do our initialization in the -layoutSubViews as there is a chance for this method to get called another time.
That is, indeed, the problem with using -layoutSubviews
for initialization: it may be called more than once, and not always at the beginning of your view's lifetime. Better to use the initialization methods.
Upvotes: 1