每个人都知道你不能相信UIViewController init / viewDidLoad方法的帧大小;这样:
- (void)viewDidLoad: {
NSLog(@"%d", self.view.frame.size.width);
}
会在很多场合打印错误的尺寸(特别是它在风景模式下几乎被打破)
这实际上会返回始终更正的结果,因此布局子视图是好的:
- (void)viewWillAppear: {
NSLog(@"%d", self.view.frame.size.width);
}
问题是每次出现视图时都会调用viewWillAppears,因此不适合分配或添加子视图。所以你最终在界面中声明每个单独的视图并最终得到了我根本不喜欢的巨大头文件,因为大多数项目在初始设置后不需要再进行任何操作
所以问题是:是否有更好的方法来处理子视图定位?
问题二是非常相关的,假设我有一个UIView的子类,包括其他各种子视图。我在我的界面中声明它,并在init / viewDidLoad方法中分配/初始化它。
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
...
menu = [[SNKSlidingMenu alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
...
}
正如我们已经知道的,我们现在需要在viewWillAppear中重新定位它以获得更准确的读数
- (void)viewWillAppear:(BOOL)animated{
....
menu.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
....
}
问题是当然所有子视图也需要重新定位。这是由自动调用的layoutSubviews函数完成的,但是我们遇到了同样的问题:所有子视图都需要在SNKSlidingMenu类的接口内声明。有没有办法解决这个问题? < / p>
感谢。
答案 0 :(得分:10)
如果您要定位iOS 5.0或更高版本,可以使用viewWillLayoutSubviews
和viewDidLayoutSubviews
进行更改。
至于你的第二个问题,如果你需要以init
之外的其他方法访问实例变量,你需要保留它,我没有看到它的问题。
但是,您可以尝试使用自动布局并在子视图之间设置规则,以便自动为您布局,而无需保留参考。
答案 1 :(得分:6)
viewDidLoad
仅在您的视图创建时被调用,但很多事情都会影响frame
的大小,并且在frame
的大小时不会再次调用它{1}}更改。
相反:
viewDidLoad
viewWillLayoutSubviews
。请参阅此处有关处理轮换的其他讨论:https://stackoverflow.com/a/16421170/1445366
答案 2 :(得分:3)
viewWillLayoutSubviews
和viewDidLayoutSubviews
可以解决此问题
但两次演出将会进行多次。
这是我的代码,以获得正确的self.view.frame
。
- (void)viewDidLoad {
[super viewDidLoad];
...
dispatch_async(dispatch_get_main_queue(), ^{
// init you view and set it`s frame. this can get correct frame.
...
}
...
}
答案 3 :(得分:0)
这不止一次挽救了我的生命(迅速4 ):
override func viewDidLoad() {
super.viewDidLoad()
self.view.setNeedsLayout()
self.view.layoutIfNeeded()
}
基本上,这会迫使viewcontroller正确地布局其视图,并从那里可以获取所有子视图的正确框架。当制作过渡动画并且视图控制器使用自动布局和界面生成器时,这特别有用。
从我注意到的情况来看,初始帧似乎设置为您的界面生成器默认大小类设置的任何值。我通常使用iPhone XS尺寸类进行编辑,因此在viewDidLoad
中,无论您是否使用iPhone XR,视图的宽度始终为375。不过,这会在viewWillAppear
之前更正。
以上代码将纠正此问题,并允许您在将视图控制器呈现到屏幕之前为视图/子视图获取正确的帧。