首页 > 解决方案 > 子视图控制器的 viewDidLayout 在父视图控制器的 viewDidLayout 之前调用

问题描述

我正在尝试制作一个类似于.popover模态演示样式视图控制器的视图控制器。因为子视图控制器中的工具提示应该基于父视图的sourceViewor布局sourceItem,所以子视图控制器引用了父视图的特定UIViewor UIBarButtonItem

(因为我在工具提示中绘制了大部分内容,所以我不能使用自动布局。)

我配置了子视图控制器的布局viewDidLayoutSubviews(),它工作正常,但是当设备方向改变时会出现问题。

当设备方向改变时,child.viewDidLayoutSubviews()调用 before parent.viewDidLayoutSubviews(),它使子视图控制器的布局基于父视图控制器在方向改变之前的旧布局。

似乎唯一弄清楚的方法是致电child.view.setNeedsLayoutfrom parent.viewDidLayoutSubviews(),但我想将其保留为 B 计划。

有没有自然的方法来处理这个?

添加

我只是做了一个示例项目来确保。

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .yellow
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        let vc = ModalViewController()
        vc.modalPresentationStyle = .overCurrentContext
        present(vc, animated: true, completion: nil)
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        print(#file)
    }
}
class ModalViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .purple
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        print(#file)
    }
}

日志如下:

// when loaded
TestProject/ViewController.swift
TestProject/ModalViewController.swift

// when rotated
TestProject/ModalViewController.swift
TestProject/ViewController.swift

标签: iosswiftuiviewcontrollerorientation

解决方案


这里有问题。layoutSubviews是自上而下传播的。如果这不是您所看到的,那么您的覆盖可能会以某种方式颠覆正常机制。确保您正在调用super所有相关的覆盖,并且您没有强制过早布局。


推荐阅读