I just want (for now) to get the dimensions of a subview on the view controller\'s instantiation.
[This is a reduction to as simple a case I can find of a previous
There is a Related issue that I am compelled to address, which hopefully will save someone else a day of debugging:
I am finding out that in Storyboard:
segue-push
does not cause subView
s to be laid out at -viewDidLayoutSubviews
(they are instead laid out at some other time just before -viewDidAppear
).segue-modal
and [navController.storyboard presentViewController:]
does cause subViews
to be laid out at -viewDidLayoutSubviews
. The solution is to put [self.mySubView layoutSubviews]
within the viewController
's -viewDidLayoutSubviews
method in order to manually load the subView
s within mySubView
.
My case was that I had a custom gradient button that was not properly initializing it's visual appearance.
The button was contained within a scrollView
that contained a CustomView
which contained the custom gradient button.
So, basically... a button within a view within a scrollView
.
The app starts out with a UINavigationController
having some other ViewController1
loaded.
ViewController1
contains a button which, when pressed, launches a storyboard segue-push
to ViewController2
.
(this was arranged in storyboard by control-dragging from the button in ViewController1
to ViewController2
).
ViewController2
contains the scrollview
/customView
/customButton
.
In ViewController2
's -viewDidLayoutSubviews
, I initialize the customButton
which is a custom Gradient Button having it's own .h/.m files.
GradientButton.m
has an initLayers
method which configures it graphically and requires the bounds
/frame
property of the button to be initialized.
However...
in ViewController2
's -viewDidLayoutSubviews
, self.customButton
had a frame of 0,0,0,0.
[super viewDidLayoutSubviews]
at the beginning of -viewDidLayoutSubviews
. -viewDidLayoutSubviews
is self.view
(ViewController2
's initial view, as connected in Storyboard's connections panel. in my case - self.view
is a scrollView
).ViewController2
, I created an outlet self.bottomView
for the view that contained self.customButton
. ViewController2
's -viewDidLayoutSubviews
, I call [self.bottomView layoutSubviews]
customButton
's frame/bounds to be properly set. [self.customButton initLayers]
which now properly initializes my custom gradient button. A few notes about ViewController2
's -viewDidLayoutSubviews:
calling [self.view layoutSubviews]
causes bottomView
's frame to be initialized, but NOT customButton
's frame.
In terms of a view hierarchy, -layoutSubviews
applies only to the subView
s of self.view
and not to any subView
s of those subView
s.
This only appears to be the case with storyboard segue-push
.
The storyboard segue-modal
and the programmatic [navController presentViewController]
both seem to correctly initialize all levels of the view hierarchy (all "subView
s of subView
s") by the time -viewDidLayoutSubviews
is called.
Those dimensions are calculated and set when the call to layoutSubviews
is made, which occurs after viewWillAppear
. After layoutSubviews
is called on the UIVIew you can get the dimensions.
Look at implementing this method in your view controller: viewDidLayoutSubviews
. At this point you should be able to get dimensions of your subviews. Note that this call is available starting in iOS 5.0 but since you reference storyboards I assume you are working at or above that anyway.
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
NSLog(@"View Controller did layout subviews. firstViewFirstSubView: %@ ", firstViewFirstSubView);
NSLog(@"subView's dimmensions: %f by %f at %f, %f", firstViewFirstSubView.frame.size.width,
firstViewFirstSubView.frame.size.height,
firstViewFirstSubView.frame.origin.x,
firstViewFirstSubView.frame.origin.y);
}