【问题标题】:UIViewController viewDidLoad incorrect width/heightUIViewController viewDidLoad 不正确的宽度/高度
【发布时间】:2013-05-23 16:53:21
【问题描述】:

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

谢谢。

【问题讨论】:

  • 使用自动布局,还是设置自动调整大小的蒙版?

标签: ios objective-c uiview


【解决方案1】:

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

关于你的第二个问题,如果你需要通过init以外的其他方法访问实例变量,你需要保留它,我看不出有什么问题。

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

【讨论】:

  • 同意,但是必须使用 initWithFrame 来初始化每个视图是非常愚蠢的。对我来说似乎有很多重复的代码,并且似乎迫使您使用大量实例变量。自动布局仅适用于较新的 iOS。
  • 旧的autoresizingMask 对你来说可能也足够了。至于重复代码:如果您要复制很多代码,您可以创建自定义UIView 子类,这样您就不会重复,或者拥有为您创建视图的辅助方法。如果您发布更多代码,我们可能会为您提供更多帮助。
【解决方案2】:

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

改为:

  • viewDidLoad 中创建子视图
  • 将它们的大小设置为 viewWillLayoutSubviews

在此处查看有关处理轮换的其他讨论:https://stackoverflow.com/a/16421170/1445366

【讨论】:

    【解决方案3】:

    viewWillLayoutSubviewsviewDidLayoutSubviews 可以解决这个问题。
    但是这两种方法会执行更多次。 这是我得到正确的代码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.   
       ...  
      }  
      ...  
    }
    

    【讨论】:

    • 这是唯一对我有用的解决方案。尽管如此,它有点难看,因为在 dispatch_async 启动之前的瞬间会弹出一些奇怪的初始视图。对于 Swift4: DispatchQueue.main.async { }
    【解决方案4】:

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

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

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

    据我所知,初始帧似乎设置为您的界面构建器的默认大小类设置为。我通常使用 iPhone XS 尺寸类进行编辑,因此在viewDidLoad 中,无论您是否使用 iPhone XR,视图的宽度似乎始终为 375。不过,这会在 viewWillAppear 之前自行纠正。

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

    【讨论】:

    • 从 xib 中创建 vc,看看这行不通
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-01
    相关资源
    最近更新 更多