如何创建一个 header 层,在多个 ViewController 中保持不变?

How to create a header layer that would stay the same over several ViewControllers?

我想创建一个 header,它在我的包含多个 ViewController 的应用程序中根本不会移动。我的 header 只是一个包含徽标 (UIImageView)、UIButton 和 UILabel 的视图。我听说我可以使用 UINavigationController 或通过向 UIWindow 添加子视图来做到这一点,但它对我不起作用(也许我做错了)。我的主要问题是在 segue 动画期间将其固定在屏幕顶部(如 hud?),并且我还需要能够在应用程序过程中修改 UILabel 的内容。

我在 Xcode 13 上工作,在 iPad 上为 iOS 15 制作故事板。 希望我说得够清楚了。

编辑 看来在 UIWindow 中插入一个视图对我来说是最好的解决方案,尽管我不确定如何正确地做到这一点。我找到的所有示例都不起作用,并且是 deprecated/outdated.

您可以创建自定义 UITabBarController,然后将其添加到 SceneDelegate 作为 -

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
        // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
        // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
        
        let vc = CustomTab()
        self.window?.rootViewController = vc
        self.window?.makeKeyAndVisible()
        .......

在自定义 TabBar 中将所有导航控制器添加为 -

viewControllers = [nav1, nav2, nav3, nav4]

并且在每个视图控制器中 class 您可以隐藏、更改或修改标签栏属性。

最后我成功地使用了 Imran 的方法,我添加了一些东西来满足我的需要。

我的 header ViewController 有一个单例 class,其中包含我需要的元素。

let HEADER = STORYBOARD.instantiateViewController(withIdentifier: "HeaderLayer") as? HeaderViewController

class HeaderViewController: UIViewController {

    @IBOutlet weak var ThemeLabel: UILabel!
    @IBOutlet weak var DifficultyImage: UIImageView!
    @IBOutlet weak var ExitButton: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()
        // ...
    }

    // Methods
}

下面是我如何将我的 header 放在 UIWindow 中以使其出现在屏幕顶部,即使在 segue 动画期间它也会保持固定。我更改了框架,因为在全屏模式下它会禁用下方视图的交互。

let STORYBOARD = UIStoryboard(name: "Main", bundle: nil)

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    
        HEADER!.view.frame = CGRect(x: 0, y: 0, width: 1366, height: 142)
        window?.addSubview(HEADER!.view)
        window?.makeKeyAndVisible()
    
        // ...
    }
    // ...
}

然后每次出现我的 ViewController 时都必须将 header 放在前面。

class ViewController: UIViewController {

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
    
        let window = UIApplication.shared.keyWindow
        window?.bringSubviewToFront(HEADER!.view)
    
        // ...
    }
}

我没有使用任何 UINavigationControllerUITabBarController,但可以使用此方法。

我遇到的唯一问题是 UIApplication.shared.keywindow 已被弃用。但是好像没有什么问题,我也没有找到解决方法。