3

如果我想以编程方式初始化视图,应该在视图控制器生命周期的哪个位置发生这种情况?

最初的直觉是loadView。但是,在这里,我们还没有视图本身的框架(计算视图的大小/位置所必需的)。viewDidLoad同上。

下一个直觉是viewWillAppear - 在这里我们(最终)保证了视图的框架。但是,这有可能在整个 vc 生命周期中被多次调用。同上viewDidAppear等...

最后,我找到了viewWillLayoutSubviews这适用于大多数静态布局的初始化 - 但是,每当任何视图移动时,都会再次调用它(与viewWillAppear相同的问题)。

我已经看到建议在loadView中初始化视图并在viewWillLayoutSubviews中设置它们的框架(因为设置框架应该是幂等的,谁在乎它是否被调用了几次)。但是为什么苹果如此强烈地鼓励initWithFrame:作为 UIViews 的标准初始化方法(https://developer.apple.com/library/ios/documentation/windowsviews/conceptual/viewpg_iphoneos/CreatingViews/CreatingViews.html)?

将我所有的 UIViewController 子类化为具有initWithViewFrame:方法会不会很疯狂?这样我可以传入一个框架,立即在loadView中手动设置它并完成它?还是最好在viewWillAppear中有一个viewHasBeenFormatted标志,如果未设置,则调用视图的格式然后设置它?

或者这只是苹果的说法“使用界面生成器,否则你就完蛋了”?

任何帮助表示赞赏!

编辑- 不小心写了 loadView 我的意思是 viewWillAppear (在最后一段)

更新- 我想我已经接受了这样一个事实,即没有地方可以

  1. 框架是众所周知的
  2. 该代码只会运行一次(在设置时)

看起来你应该initWithFrame:你在viewDidLoad中的所有视图(但是我猜那个视图的内容不应该将该帧视为远程最终帧?因为它是根据假设得出的呢?呃。 ..)。然后在layoutSubviews中重新设置它们的框架。并确保手动处理初始布局和布局之间的差异,因为那里移动了视图......伙计,我觉得我必须遗漏一些东西......(哈哈否认......)

我想,或者提交并使用 IB。

update2 - viewWillLayoutSubviews 将在其子视图之一被调整大小时被调用。所以它仍然不合格,因为它不符合我正在寻找的所需特征的属性 2。:(

4

3 回答 3

3

If you're doing layout with IB, it's fine to do additional view initialization in viewDidLoad (for example, if you need to do stuff that IB doesn't handle well, or if you have UIView subclasses with properties not supported by IB). Alternatively, if you're not using IB, the documentation says you should use loadView to manually initialize your view hierarchy.

You're right, though, that you can't rely on the frame being accurate at that point. So you can accomplish layout via each view's autoResizingMask property, layout constraints (if you're iOS 6 and later), and/or overriding layoutSubviews.

My usual approach is to do layout to some degree in IB, then do anything else I need to (nontrivial layout, custom classes, etc) in viewDidLoad. Then, if I have layout to figure out that autoResizingMask doesn't cover (I'm supporting down to iOS 5), I override viewWillAppear (or layoutSubviews if I'm subclassing UIView) and do some pixel math. I've got a category on UIView to help with this that has things like:

-(void)centerSubviewHorizontally:(UIView *)view pixelsFromTop:(float)pixels;
-(void)centerSubviewHorizontally:(UIView *)view pixelsBelow:(float)pixels siblingView:(UIView *)sibling;
于 2013-09-06T15:11:14.823 回答
2

视图控制器不应该方法initWithFrame:。我在所有代码中所做的(我从不使用 IB)是让默认值loadView做自己的事情。我在viewDidLoad. 此时,视图控制器的框架至少有一个合理的值。所有子视图都可以根据视图控制器视图的初始大小使用自己的健全框架创建。使用适当的autoresizingMask值,这可能就是您所需要的。

如果您需要更具体的子视图布局,请将相应的布局代码放入viewWillLayoutSubviews方法中。这将处理任何视图控制器视图框架更改,包括旋转、通话状态栏等。

于 2013-09-06T15:11:25.113 回答
0

如果您不使用界面构建器,您应该覆盖 loadView 并在那里初始化视图。如果你使用自动布局,你也可以在那里添加你的约束。如果您不使用自动布局,您可以覆盖视图的 layoutSubviews 方法来调整框架。

于 2013-09-06T15:02:42.607 回答