UIHostingController adds unremovable NavigationBar

A stack overflow posts show this problem:

https://stackoverflow.com/questions/63652728/swift-ui-hostingcontroller-adds-unwanted-navigation-bar

When I add a UIHostingController to my UIKit app it adds a navbar that cannot be removed. This nav bar covers some buttons for me, while other buttons work these ones on the nav bar area on top get blocked but are visible.

I tried removing the nav bar on the UIHostingController wrapper, every ViewController, and the SwiftUI Views.

Am I missing something? I just want to show a List inside my UIView!

Code:

UIHostingController Wrapper

import UIKit
import SwiftUI

class ControlledNavigationHostingController<Content>: UIHostingController<AnyView> where Content: View {
  public init(shouldShowNavigationBar: Bool, rootView: Content) {
    super.init(rootView: AnyView(rootView.navigationBarHidden(!shouldShowNavigationBar)))
    navigationController?.isNavigationBarHidden = true
  }
  @objc required dynamic init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }
}

My List

import SwiftUI

struct OverallContentListView: View {
   
  var sections = [0,1,2,3,4]
   
  var body: some View {
    NavigationView {
        List(sections, id: \.self) { section in
          Text("TEST")
        }
    }
    .navigationBarTitle("", displayMode: .inline)
    .navigationBarHidden(true)
  }
}

UIViewController

import UIKit
import SwiftUI

class TurnoverSplitViewController: UIViewController, ContentDisplayer, StoryboardInstantiable, TurnoverSectionSelectionDelegate {
   
  @IBOutlet weak var contentContainer: UIView!
  private var splitContentViewController = ControlledNavigationHostingController(shouldShowNavigationBar: true, rootView: OverallContentListView())
        
  override func viewDidLoad() {
    super.viewDidLoad()

    navigationController?.isNavigationBarHidden = true
    navigationController?.setNavigationBarHidden(true, animated: false)
    addContent(child: splitContentViewController, to: contentContainer)
  }
   
  override func viewDidAppear(_ animated: Bool) {
    navigationController?.setNavigationBarHidden(false, animated: false)
    super.viewDidAppear(true)
  }

   func addContent(child viewController: UIViewController, to: UIView? = nil) {
    // Add Child View Controller
    addChild(viewController)

    // Add Child View as Subview
    if let container = to == nil ? contentContainer : to {
      container.addSubview(viewController.view)
      // Configure Child View
      viewController.view.frame = container.bounds
      viewController.view.translatesAutoresizingMaskIntoConstraints = true
      // Notify Child View Controller
      viewController.didMove(toParent: self)
    }
  }
}
Add a Comment

Accepted Reply

Please forgive me lol but this was the fix, I had setNavigationBarHidden(false... instead of true

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

Replies

Please forgive me lol but this was the fix, I had setNavigationBarHidden(false... instead of true

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

Your SwiftUI body creates a NavigationView to wrap your list. If you don't want a navigation bar (and everything else that comes with NavigationView) then don't wrap your list in one.

After long attempts, I have the same behavior in my UIKit project and SwiftUI Views with UIHostingController as with just UIKit.

In my storyboard, the UIHostingController is embedded in the NavigationController and this in turn is connected to the UITab Bar Controller. The first thing to do is to uncheck "Shows Navigation Bar" in the Attributes Inspector of the NavigationController. In the SwiftUI View I have the list in the NavigationView with the modifier .navigationBarTitle ("ViewTitle", displayMode: .large) and the next SwiftUI Views without NavigationView and the list with .navigationBarTitle ("SecondViewTitle", displayMode: .inline) modifier. The best solution for me.