将swiftUI嵌入UIkit时无法隐藏navigationBar

时间:2019-11-05 04:49:58

标签: swift uiviewcontroller uikit uinavigationbar swiftui

当我将某些 swiftUI 放在Secondary Axis val_1内时,我试图隐藏navigationBar

UIKit

但是它并没有消失。当我拿走 swiftUI 时,它可以工作。有人知道如何解决这个问题吗?

编辑:

我正在实例化这样的视图 viewController 视图是swiftUI,然后将其添加到UIView()中,就像添加任何UIKit元素一样。

6 个答案:

答案 0 :(得分:3)

当在viewDidAppear中而不是viewWillAppear中调用setNavigationBarHidden时,隐藏正在扩展UIHostingController的类中的导航栏似乎可以工作。

override func viewDidAppear(_ animated: Bool) {
    navigationController?.setNavigationBarHidden(true, animated: false)
    super.viewDidAppear(animated)
}

答案 1 :(得分:3)

昨天也遇到了这个问题。

我正在展示一个带有 UINavigationController 的模态 UIViewController 作为 rootViewController,它通过 UIHostingController 嵌入了一个 SwiftUI 视图。

在嵌入 SwiftUI 视图后,在 setNavigationBarHiddenviewDidAppear 中设置通常的 UIViewController 将停止工作。

概述:

Root ViewController: setNavigationBarHidden in viewWillAppear

Navigation Bar Visible:
UINavigationController > root UIViewController > embedded UIHostingController

Navigation Bar Invisible:
UINavigationController > root UIViewController > no UIHostingController

经过一些调试后,我意识到 UIHostingController 本身再次调用了 setNavigationBarHidden

所以这个问题的原因是,UIHostingControllers 改变了周围的 UINavigationControllerUINavigationBar

一个简单的修复:

在您的 UIHostingController 嵌入的第一个显示的 SwiftUI 视图中设置导航栏属性。

    var body: some View {
        MyOtherView(viewModel: self.viewModel)
            .navigationBarHidden(true)
    }

这将恢复 SwiftUI 和 UIHostingController 正在尝试应用到您周围的 UINavigationController 的调整。

由于无法保证 SwiftUI 和 UIKit 之间的交互(它使用底层 UIKit),我建议将 setNavigationBarHidden 与此修饰符一起保留在周围的 viewDidAppear 中。

答案 2 :(得分:2)

UIHostingViewController尊重SwiftUI视图的navigationBarHidden值。您可以在SwiftUI视图的末尾调用.navigationBarHidden(true),也可以使用下面示例中显示的自定义UIHostingController子类。

解决方案:

import SwiftUI
import UIKit

class YourHostingController <Content>: UIHostingController<AnyView> where Content : View {

  public init(shouldShowNavigationBar: Bool, rootView: Content) {
      super.init(rootView: AnyView(rootView.navigationBarHidden(!shouldShowNavigationBar)))
  }

  @objc required dynamic init?(coder aDecoder: NSCoder) {
      fatalError("init(coder:) has not been implemented")
  }
}

用法示例:

let hostVc = YourHostingController(shouldShowNavigationBar: false, rootView: YourSwiftUIView())

答案 3 :(得分:1)

我想在这里包括我的方法,以防万一有人在使用SwiftUI时发现它有用。 我发现问题是UIHostingController在我的声明中覆盖了

navigationController?.setNavigationBarHidden(true, animated: false)

所以我刚刚创建了一个自定义UIHostingController并使用了viewWillAppear(_animated:Bool):

class UIHostingViewControllerCustom:UIHostingController<YourView>{
  override func viewWillAppear(_ animated: Bool) {
    navigationController?.setNavigationBarHidden(true, animated: false)
  }
}

然后,当您将该UIHostingController添加到ViewController中时:

let hostingController = UIHostingViewControllerCustom(rootView: YourView())
hostingController.view.backgroundColor = .clear
addChild(hostingController)
hostingController.view.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(hostingController.view)
hostingMapView.didMove(toParent: self)

//Constraints
hostingController.view.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
hostingController.view.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
hostingController.view.topAnchor.constraint(equalTo:  self.view.safeAreaLayoutGuide.topAnchor, constant: -view.safeAreaInsets.top).isActive = true
hostingController.view.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor, constant: -view.safeAreaInsets.bottom).isActive = true

答案 4 :(得分:0)

您知道在swiftUI的UIKit函数中放置的位置吗?

内部
var body: some View {

}

您需要调用ViewControllerWrapper类,该类需要包含一些方法才能使用UIKit类。 UIViewControllerRepresentable实现也需要。

答案 5 :(得分:0)

没有任何效果,所以我添加了一个观察者来隐藏父视图中的 navigationBar

    private var observer: NSKeyValueObservation?


    override func viewDidLoad() {
        super.viewDidLoad()

        observer = navigationController?.observe(
            \.navigationBar.isHidden,
            options: [.new]
        ) { [weak self] _, change in
            guard change.newValue == false else { return }
            self?.navigationController?.navigationBar.isHidden = true
        }
    }