I have a UIView viewForRootVc
that is a declared property for a UIView subclass NewView
. It's NewView
's responsibility to initialize viewForRootVc
, but then a subclass NewViewSubClass
sets its background color. Once this is all done, the root view controller RootVc
adds viewForRootVc
as a subview to its view.
But this doesn't work. viewForRootVc
doesn't actually get added.
It DOES work, however, if I do any of the following three things (keep in mind that I am using ARC):
- Rather than setting the background color of
viewForRootVc
inNewViewSubClass
, I set it inNewView
. And then, rather than initializing an instance ofNewViewSubClass
, I simply initialize an instance ofNewView
. - When initializing
viewForRootVc
inNewView
, I call the setter (i.e. self.viewForRootVc) rather than just using direct assignment. - List
viewForRootVc
as an ivar in the header file ofNewView
.
I don't understand why any of these three things are necessary.
Here's the code that does NOT work: RootVc.m
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NewView *newView = [[NewViewSubClass alloc] initWithFrame:CGRectMake(0, 0, 300, 300)];
//logs 0.00000, 0.00000
NSLog(@"%f, %f",newView.viewForRootVc.frame.size.width, newView.viewForRootVc.frame.size.height);
[self.view addSubview:newView.viewForRootVc];
//logs 0
NSLog(@"subviews: %i",[self.view.subviews count]);
}
NewView.h
@property (nonatomic, retain) UIView *viewForRootVc;
NewView.m
@synthesize viewForRootVc;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
viewForRootVc = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
}
return self;
}
NewViewSubClass.m
@synthesize viewForRootVc;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
viewForRootVc.backgroundColor = [UIColor greenColor];
}
return self;
}
One thing I noticed is that if I do specify viewForRootVc
as an ivar, I don't need to put @synthesize viewForRootVc;
in the implementation file of NewViewSubClass
.
I always understood declared properties to effectively achieve the following:
- Allow other objects to access them.
- Allow a setter to be called when desired.
- If not using ARC, calling the setter will automatically retain the property if you specified
retain
in the property declaration. - Under ARC, an ivar is automatically generated for any declared properties.
But clearly there is more to it than this. I'm not sure if it's a scope issue, or if my non-working code above ends up creating two distinct versions of viewForRootVc
-- perhaps one that has the correct frame as specfied in NewView
's init
method and one that has the correct background color as specified in NewViewSubClass
's init
method, but neither has both the right frame and color.
I'm very much hoping someone can clarify once and for all for me the implications of declared properties vs. ivars, as well as calling the setter to set a declared property vs. assigning it a value directly.