首页 > 解决方案 > 从 xib 加载视图控制器返回错误的帧

问题描述

从 xib 加载视图控制器时遇到问题

我有一个 xib 文件,其中包含一个视图控制器和一个子视图,如下图所示。请注意,我iPhone 11 Pro Max在 xib 中使用(屏幕宽度 = 414)

子视图有 8 个前导和尾随到其父视图。

在此处输入图像描述

问题是当我在 iPhone 12 Pro Max(屏幕宽度 = 428)上运行应用程序时,我检查屏幕尺寸和子视图尺寸的值,它返回奇怪的值。这是我的代码:


public override func viewDidLoad() {
        super.viewDidLoad()
        
        print(view.frame) // (0.0, 0.0, 414.0, 896.0)
        print(collageView.frame) // (8.0, 210.0, 398.0, 398.0)

    }
    
    public override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        
        print(view.frame) // (0.0, 0.0, 428.0, 926.0) updated
        print(collageView.frame) // (8.0, 210.0, 398.0, 398.0) ??
        
        let width = collageView.frame.width
        let height = collageView.frame.height
        
        let frames = self.frames?(CGSize(width: width, height: height)) ?? []
        
        for i in 0..<frames.count {
            let componentView = CropComponentView(frame: frames[i])
            componentView.image = images[i]
            collageView.addSubview(componentView)
        }
    }
  

我的问题是:

我们如何在 viewDidLoad 中获得正确的屏幕尺寸?为什么子视图的框架不像屏幕尺寸那样更新?

标签: iosswiftxib

解决方案


我们如何在 viewDidLoad 中获得正确的屏幕尺寸?

排序的答案是您无法在 viewDidLoad() 中获得最终视图(viewController)的大小,因为该视图只是从 xib 加载的,并且具有在 xib 中设置的占位符框架。需要将其添加到视图层次结构中(例如,添加到父视图/窗口),然后才能应用布局规则。视图将在视图加载后立即添加。

控制器可用的宽度/高度由容器控制器(如果有)以及设备方向和状态栏状态决定。例如,如果您的控制器被添加到 tabbarcontroller 中,那么如果 tabbar 正在显示,它将具有更少的垂直空间。如果显示状态栏并且您有来电,则状态栏的大小将发生变化,留下更少的垂直空间。如果您在 SplitViewController 容器中显示您的控制器,那么它将具有较小的宽度等。

如果您假设它将占用整个屏幕尺寸,您可以在 viewDidLoad() 中计算框架:

    override func viewDidLoad()  {
       //...
       var screenSize = UIScreen.main.bounds
       var collageViewFrame: CGSize = self.collageView.frame.sizeThatFits(screenSize)
    } 

为什么子视图的框架不像屏幕尺寸那样更新?

文档-viewDidLayoutSubviews

但是,调用此方法并不表示视图的子视图的各个布局已被调整。

如果您需要正确的框架,则需要layoutIfNeeded在该子视图中调用方法。Se也这个答案。


推荐阅读