10

每个人都知道你不能相信 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 类的接口内声明。有没有办法解决这个问题?

谢谢。

4

4 回答 4

11

如果您的目标是 iOS 5.0 或更高版本,您可以使用viewWillLayoutSubviewsviewDidLayoutSubviews进行更改。

至于您的第二个问题,如果您需要以其他方法访问实例变量init,则需要保留它,我认为它没有问题。

但是,您可以尝试使用自动布局并在子视图之间设置规则,以便自动为您布局,而无需保留参考。

于 2013-05-28T16:21:50.130 回答
6

viewDidLoad仅在您的视图创建时被调用,但很多事情会影响的大小,并且在更改frame时不会再次调用它。frame

反而:

  • 在中创建子视图viewDidLoad
  • 将它们的尺寸设置为 viewWillLayoutSubviews.

请参阅此处的一些其他讨论以处理轮换:https ://stackoverflow.com/a/16421170/1445366

于 2013-05-28T16:19:13.347 回答
5

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.   
   ...  
  }  
  ...  
}
于 2016-10-09T07:43:04.463 回答
0

这不止一次救了我的命(Swift 4):

override func viewDidLoad() {
    super.viewDidLoad()
    self.view.setNeedsLayout()
    self.view.layoutIfNeeded()
}

基本上,这会迫使 viewcontroller 正确布局它的视图,并且从那里您可以获得所有子视图的正确帧。这在进行过渡动画并且您的视图控制器正在使用自动布局和界面构建器时特别有用。

从我注意到的情况来看,初始帧似乎设置为界面构建器的默认大小类设置的任何值。我通常使用 iPhone XS 尺寸类进行编辑,因此viewDidLoad无论您是否使用 iPhone XR,视图的宽度似乎始终为 375。不过,这之前会自行纠正viewWillAppear

上面的代码将纠正这个问题,并允许您在视图控制器呈现到屏幕之前为您的视图/子视图获取正确的帧。

于 2019-05-09T10:50:55.210 回答