在 UIkit 中嵌入 swiftUI 时无法隐藏导航栏

Mik*_*ats 12 uinavigationbar uiviewcontroller uikit swift swiftui

我试图navigationBar在将一些swiftUI放入 a时隐藏UIKit viewController

override func viewWillAppear(_ animated: Bool) {
   super.viewWillAppear(animated)
   self.navigationController?.setNavigationBarHidden(true, animated: animated)
Run Code Online (Sandbox Code Playgroud)

但它不会消失。当我拿走swiftUI 时,它仍然有效。有谁知道如何解决这个问题?

编辑:

我正在实例化一个这样的视图 let controller = UIHostingController(rootView:view()) ,其中视图是 swiftUI,然后像添加任何 UIKit 元素一样将其添加到 UIView() 中。

Gus*_*lad 25

在我们的例子中使用修饰符.navigationBarHidden(true)不起作用。但没有效果。

我们的解决方案是子类化并且根本UIHostingController不让它访问。UINavigationController例如:

import UIKit
import SwiftUI

final public class RestrictedUIHostingController<Content>: UIHostingController<Content> where Content: View {

    /// The hosting controller may in some cases want to make the navigation bar be not hidden.
    /// Restrict the access to the outside world, by setting the navigation controller to nil when internally accessed.
    public override var navigationController: UINavigationController? {
        nil
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,此解决方案依赖于 UIKit 和 SwiftUI 中的底层代码来访问UINavigationController并根据UIViewController.navigationController-property 设置导航栏隐藏状态。如果苹果决定改变这一假设,这种情况将来可能会被打破。


Fre*_*orf 13

昨天也遇到这个问题了。

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

一旦嵌入 SwiftUI 视图,设置通常的设置setNavigationBarHidden就会停止工作。viewDidAppearUIViewController

概述:

Root ViewController: setNavigationBarHidden in viewWillAppear

Navigation Bar Visible:
UINavigationController > root UIViewController > embedded UIHostingController

Navigation Bar Invisible:
UINavigationController > root UIViewController > no UIHostingController
Run Code Online (Sandbox Code Playgroud)

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

所以这个问题的原因是,改变了UIHostingControllers周围的UINavigationController环境UINavigationBar

一个简单的修复:

在 . 中嵌入的第一个呈现的 SwiftUI 视图中设置导航栏属性UIHostingController

Root ViewController: setNavigationBarHidden in viewWillAppear

Navigation Bar Visible:
UINavigationController > root UIViewController > embedded UIHostingController

Navigation Bar Invisible:
UINavigationController > root UIViewController > no UIHostingController
Run Code Online (Sandbox Code Playgroud)

这将恢复 SwiftUI 的调整,并UIHostingController尝试将其应用到您周围的UINavigationController.

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


TPa*_*zek 12

UIHostingViewController 尊重navigationBarHiddenSwiftUI 视图的价值。您可以.navigationBarHidden(true)在 SwiftUI 视图的末尾调用,也可以使用下面示例中显示的自定义 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")
  }
}
Run Code Online (Sandbox Code Playgroud)

用法示例:

let hostVc = YourHostingController(shouldShowNavigationBar: false, rootView: YourSwiftUIView())
Run Code Online (Sandbox Code Playgroud)

  • 我爱你,伙计。几个小时的工作,在 UINavigationBar 上尝试不同的东西......你救了我。多谢! (2认同)

小智 11

就我而言,我必须使用这个 UIHostingController 子类。

class NavigationBarHiddenUIHostingController<Content: View>: UIHostingController<Content> {
  override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()
    if navigationController?.isNavigationBarHidden == false {
      navigationController?.isNavigationBarHidden = true
    }
  }
}
Run Code Online (Sandbox Code Playgroud)


Mik*_*ika 9

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

override func viewDidAppear(_ animated: Bool) {
    navigationController?.setNavigationBarHidden(true, animated: false)
    super.viewDidAppear(animated)
}
Run Code Online (Sandbox Code Playgroud)


小智 7

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

navigationController?.setNavigationBarHidden(true, animated: false)
Run Code Online (Sandbox Code Playgroud)

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

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

然后,当您将该 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
Run Code Online (Sandbox Code Playgroud)


Bar*_*man -7

你知道你把 UIKit 函数放在 swiftUI 的什么地方吗?

代替

var body: some View {

}
Run Code Online (Sandbox Code Playgroud)

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