如果我想以编程方式初始化视图,那么viewcontroller生命周期中应该发生什么?
最初的直觉是 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)?
将所有我的UIViewControllers子类化为 initWithViewFrame:方法会不会很疯狂?那样我可以传入一个框架,立即在 loadView 中手动设置它并完成它?或者在 viewWillAppear 中有一个 viewHasBeenFormatted 标志更好,如果没有设置,会调用视图的格式然后设置它吗?
或者这只是苹果说“使用界面构建器还是你搞砸了”的方式?
感谢任何帮助!
编辑 - 意外地写了一个loadView,我的意思是viewWillAppear(在最后一段)
更新 - 我想我已经接受了这样一个事实:没有地方
在 viewDidLoad 中看起来你应该 initWithFrame:你的所有观点(但我想这个视图的内容不应该像远程那样对待那个帧)最后?因为它是如何在假设的基础上得出的?呃......)。然后在 layoutSubviews 中重新设置其框架。并确保手动处理初始布局和布局之间的差异,因为在那里移动了视图......我觉得我很想丢失一些东西......(笑声否认......)
我想,或者提交并使用IB。
update2 - viewWillLayoutSubviews将调整其中一个子视图的大小。所以它仍然被取消资格,因为它失败了我正在寻找的所需特性的属性2。 :(
答案 0 :(得分:3)
如果您正在使用IB进行布局,可以在viewDidLoad
中进行额外的视图初始化(例如,如果您需要执行IB处理不当的内容,或者您有{{1}具有IB不支持的属性的子类)。或者,如果您不使用IB,则documentation表示您应使用UIView
手动初始化视图层次结构。
但是,你是对的,你不能依赖于那时的准确框架。因此,您可以通过每个视图的loadView
属性,布局约束(如果您是iOS 6及更高版本)和/或覆盖autoResizingMask
来完成布局。
我通常的方法是在IB中进行某种程度的布局,然后在layoutSubviews
中做我需要的任何其他事情(非平凡的布局,自定义类等)。然后,如果我有布局来确定viewDidLoad
没有涵盖(我支持iOS 5),我会覆盖autoResizingMask
(或viewWillAppear
如果我正在进行子类化{ {1}})并做一些像素数学运算。我在layoutSubviews
上有一个类别来帮助解决这个问题:
UIView
答案 1 :(得分:2)
视图控制器应不具有initWithFrame:
方法。我在所有代码(我从不使用IB)中所做的是让默认的loadView
做自己的事情。我在viewDidLoad
中创建并设置了所有子视图。此时,视图控制器的框架至少具有合理的值。可以使用基于视图控制器视图的初始大小的自己的理智帧创建所有子视图。使用适当的autoresizingMask
值,这可能就是您所需要的。
如果您需要更具体的子视图布局,请在viewWillLayoutSubviews
方法中放置相应的布局代码。这将处理任何视图控制器视图帧更改,包括旋转,通话中状态栏等
答案 2 :(得分:0)
如果您不使用界面构建器,则应覆盖loadView并在那里初始化视图。如果您使用autolayout,您还可以在那里添加约束。如果您不使用自动布局,则可以覆盖视图的layoutSubviews方法以调整帧。