在Storyboard中获取子视图的框架

我只想(现在)来获取视图控制器实例化上的子视图的维度。

[这是一个简单的例子,我可以find以前的问题 。 我试图弄清楚为什么Storyboard中的场景的子视图并不像我期望的那样运行,也就是说:像XIB一样 – 我只是想在我们的子视图的尺寸实际绘制到屏幕之前得到它的尺寸]

为了把问题简化成一个新的,干净的项目,我这样做:

  • 创build一个新的单视图项目“使用故事板”选中
  • 将一个UIView添加到默认的MainStoryboard_iPad.storyboard (并将其背景更改为绿色以使其更容易看到 – 除了缩小尺寸之外,这是我从默认UIView拖到场景中所做的唯一更改)
  • 在浏览器中单击ViewController.h文件,将其置于Storyboard框架下面的自己的框架中,并在@interface指令下面插入一对大括号
  • 控制单击并拖动从故事板中的UIView到ViewController.h并告诉它命名出口firstViewFirstSubView

所以我们现在有ViewController.h

 #import <UIKit/UIKit.h> @interface ViewController : UIViewController { IBOutlet UIView *firstViewFirstSubView; } @end 

然后,我将这个方法添加到ViewController.m:

 - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; NSLog(@"View Controller will appear. 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); } 

在这一点上,我期望能够得到UIView子视图的维度。 但是我得到所有的0,

 2012-11-15 15:21:00.743 StoryboardViewBounds[11132:c07] View Controller will appear. firstViewFirstSubView: <UIView: 0x9379730; frame = (0 0; 0 0); autoresize = TM+BM; layer = <CALayer: 0x9378e40>> 2012-11-15 15:21:00.744 StoryboardViewBounds[11132:c07] subView's dimmensions: 0.000000 by 0.000000 at 0.000000, 0.000000 

我究竟做错了什么? 看来这应该是非常简单的,所以我认为我必须丢失一些简单的东西,无论是在Storyboard编辑器中投入正确的开关,还是实现Storyboard所需的方法。

当调用layoutSubviews时,这些维度将被计算并设置,这会在viewWillAppear之后发生。 在UIVIew上调用layoutSubviews之后,您可以获得维度。

看看在你的视图控制器中实现这个方法: viewDidLayoutSubviews 。 在这一点上,你应该能够得到你的子视图的尺寸。 请注意,此调用在iOS 5.0中可用,但是由于您参考故事板,因此我认为您正在或高于此值。

 - (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); } 

有一个相关的问题,我不得不解决,这将有助于拯救别人一整天的debugging:

我发现在Storyboard中:

  1. segue-push不会导致子subView被放置在-viewDidLayoutSubviews它们被放置在另一个时间-viewDidAppear之前 )。
  2. segue-modal[navController.storyboard presentViewController:] 的确会导致子subViews-viewDidLayoutSubviews

解决的办法是把[self.mySubView layoutSubviews]放在viewController-viewDidLayoutSubviews方法中,以便在subView手动加载mySubView

我的情况是,我有一个自定义渐变button,没有正确初始化它的视觉外观。
该button包含在一个包含自定义渐变button的CustomView中。
所以,基本上…一个button在一个视图内的一个scrollView

该应用程序开始与一个UINavigationController有一些其他ViewController1加载。
ViewController1包含一个button,当按下这个button时,将启动一个storyboard segue-pushViewController2
这是通过控制 – 从ViewController1的button拖动到ViewController2在故事板中安排的

ViewController2包含scrollview / customView / customButton
ViewController2-viewDidLayoutSubviews ,我初始化了自定义渐变buttoncustomButton ,它具有自己的.h / .m文件。
GradientButton.m有一个initLayers方法,它以graphics方式configuration它,并要求初始化button的bounds / frame属性。
不过
ViewController2-viewDidLayoutSubviewsself.customButton有一个0,0,0,0的框架。

一些注意事项:

  1. 是的,我在-viewDidLayoutSubviews的开头调用[super viewDidLayoutSubviews]
  2. -viewDidLayoutSubviews布置的唯一视图是-viewDidLayoutSubviewsViewController2的初始视图,在Storyboard的连接面板连接。 在我的情况下 – scrollView是一个scrollView )。

解决:

  1. ViewController2 ,我为包含self.customButton的视图创build了一个socketsself.customButton
  2. ViewController2-viewDidLayoutSubviews ,我调用[self.bottomView layoutSubviews]
    • 这将导致customButton的框架/边界被正确设置。
  3. 接下来,我调用[self.customButton initLayers] ,现在正确地初始化我的自定义渐变button。

有关ViewController2-viewDidLayoutSubviews:调用[self.view layoutSubviews] -viewDidLayoutSubviews: [self.view layoutSubviews]的一些注意事项会导致bottomView的框架被初始化,但不是customButton的框架。
就视图层次而言, -layoutSubviews仅适用于subView的子视图, -layoutSubviews适用于这些subView视图的-layoutSubviews视图。
这似乎只是故事板segue-push

故事板segue-modal和编程[navController presentViewController]都似乎通过[navController presentViewController]正确初始化视图层次结构的所有级别(所有“ subView的子subView ”)。