在 Storyboard 中获取子视图的帧

Posted

技术标签:

【中文标题】在 Storyboard 中获取子视图的帧【英文标题】:Getting subViews' frames in Storyboard 【发布时间】:2012-11-15 21:31:11 【问题描述】:

我只想(目前)在视图控制器的实例化中获取子视图的尺寸。

[这是我能找到的a previous question 的简单案例。我试图弄清楚为什么 Storyboards 中场景的子视图没有按我预期的方式运行,也就是说:就像 XIB 一样 - 我只想在实际绘制到屏幕之前获取子视图的尺寸]

为了将问题浓缩为一个新的、干净的项目,我这样做:

创建一个新的单视图项目并选中“使用 Storyboard” 将单个 UIView 添加到默认现有 MainStoryboard_iPad.storyboard (并将其背景更改为绿色以使其更容易看到 - 除了缩小一些尺寸之外,这是我对拖到场景中的默认 UIView 所做的唯一更改) 选项-单击导航器中的ViewController.h 文件以将其显示在故事板框架下方的自己的框架中,并在@interface 指令下方插入一对大括号 从 Storyboard 中的 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 需要的方法。

【问题讨论】:

【参考方案1】:

这些维度是在调用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);

【讨论】:

这个成功了,谢谢!我想知道为什么布局文件中初始信息的可用性在我们使用 XIB 文件(以及我使用的所有使用 XIB 文件的教程代码,早在viewDidLoad)和他们实现 Storyboard 之间发生了变化。无论如何-谢谢!【参考方案2】:

有一个我不得不解决的相关问题,希望可以为其他人节省一天的调试时间:

我在 Storyboard 中发现了这一点:

    segue-push不会导致subViews 被布置在-viewDidLayoutSubviews它们被布置在-viewDidAppear 之前的某个其他时间)。... segue-modal[navController.storyboard presentViewController:] 确实 导致 subViews 布局在 -viewDidLayoutSubviews

解决方案是将[self.mySubView layoutSubviews] 放在viewController-viewDidLayoutSubviews 方法中,以便在mySubView 中手动加载subViews。

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

应用程序以 UINavigationController 开始,并加载了其他一些 ViewController1ViewController1 包含一个按钮,按下该按钮时,将启动故事板 segue-push 到 @987654341 @. (这是通过从ViewController1 中的按钮控制拖动到ViewController2 来安排在情节提要中的

ViewController2 包含scrollview/customView/customButton。 在ViewController2-viewDidLayoutSubviews 中,我初始化了customButton,这是一个自定义渐变按钮,有自己的.h/.m 文件。GradientButton.m 有一个initLayers以图形方式配置它并需要初始化按钮的 bounds/frame 属性的方法。但是... 在ViewController2-viewDidLayoutSubviews 中,self.customButton 的帧为 0,0,0,0。

几点说明:

    是的,我在-viewDidLayoutSubviews 的开头调用[super viewDidLayoutSubviews]。 在-viewDidLayoutSubviews 布置的唯一视图是self.viewViewController2 的初始视图,在 Storyboard 的连接面板中连接。在我的情况下 - self.viewscrollView )。

解决:

    ViewController2 中,我为包含self.customButton 的视图创建了一个出口self.bottomView。 在ViewController2-viewDidLayoutSubviews,我打电话给[self.bottomView layoutSubviews] 这将导致customButton 的框架/边界被正确设置。 接下来,我调用[self.customButton initLayers],它现在可以正确初始化我的自定义渐变按钮。

关于ViewController2-viewDidLayoutSubviews: 调用[self.view layoutSubviews] 的一些注意事项导致bottomView 的框架被初始化,但不是customButton 的框架。 在视图层次结构方面,-layoutSubviews 仅适用于 self.view 中的 subViews,而不适用于 subViews 中的任何 subViews。 只有情节提要 segue-push 才会出现这种情况。

情节提要 segue-modal 和程序化的[navController presentViewController] 似乎都正确初始化了视图层次结构的所有级别(subViews 的所有“subViews”)到时间@ 987654388@ 被调用。

【讨论】:

非常感谢,遇到完全相同的情况

以上是关于在 Storyboard 中获取子视图的帧的主要内容,如果未能解决你的问题,请参考以下文章

Xcode 6 Storyboard 为 UITextView 设置错误的帧大小

在IOS的Storyboard中隐藏子视图

ViewController 的子视图的 IBOutlets 在 Storyboard 的 viewDidLoad 中为零

快速滚动后,粘性滚动视图子视图的帧不正确。可编译的例子

Storyboard xib 实时视图在左上角呈现所有子视图

Xcode:如何为使用 Storyboard 创建的子视图设置委托?