Swift UI - HostingController adds unwanted navigation bar
Asked Answered
K

4

9

I am attempting to integrate SwiftUI into my project, and I am currently using a storyboard which is launched via my app delegate with the following code:


_rootNavigiationController = [[UINavigationController alloc] init];
_rootNavigiationController.navigationBarHidden = YES;

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:StoryboardLoginRegister bundle:nil];
BasicInformation *basicInfo = (BasicInformation *)[storyboard instantiateViewControllerWithIdentifier:@"basic-info"];
[self.rootNavigiationController setViewControllers:@[basicInfo]];

So essentially my App delegate is in objective-c and the windows root controller is a UINavigation controller.

My BasicInformation class looks like:

class BasicInfo: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        self.navigationController?.isNavigationBarHidden = true;
        // Do any additional setup after loading the view.
    }
    
    @IBSegueAction func addSwiftUi(_ coder: NSCoder) -> UIViewController? {
        let BasicInfoUI = BasicInfo_UI();
        let hostingController = UIHostingController(coder: coder, rootView: BasicInfoUI);
        hostingController?.navigationController?.isNavigationBarHidden = true;
        return hostingController;
    }
    
    /*
    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // Get the new view controller using segue.destination.
        // Pass the selected object to the new view controller.
    }
    */

}

And the Swift UI for the basic information is the following:

struct BasicInfo_UI: View {
    @State var username: String = ""
    @State var isPrivate: Bool = true
    @State var notificationsEnabled: Bool = false
    @State private var previewIndex = 0
    var previewOptions = ["Always", "When Unlocked", "Never"]

    var body: some View {
        Form {
            Section(header: Text("PROFILE")) {
                TextField("Username", text: $username)
                Toggle(isOn: $isPrivate) {
                    Text("Private Account")
                }
            }
            
            Section(header: Text("NOTIFICATIONS")) {
                Toggle(isOn: $notificationsEnabled) {
                    Text("Enabled")
                }
                Picker(selection: $previewIndex, label: Text("Show Previews")) {
                    ForEach(0 ..< previewOptions.count) {
                        Text(self.previewOptions[$0])
                    }
                }
            }
            
            Section(header: Text("ABOUT")) {
                HStack {
                    Text("Version")
                    Spacer()
                    Text("2.2.1")
                }
            }
            
            Section {
                Button(action: {
                    print("Perform an action here...")
                }) {
                    Text("Reset All Settings")
                }
            }
        }
    }
}

struct BasicInfo_UI_Previews: PreviewProvider {
    static var previews: some View {
        BasicInfo_UI()
    }
}

My only issue is i can't seem to figure out why i have a navigation bar at the top of the UI in my app

Unwanted navigation bar

Hoping somebody can explain to me why exactly there is a navigation bar at the top of my controller event though i've explicitly set navigationbarhidden to true in multiple places in my app

Korenblat answered 29/8, 2020 at 23:35 Comment(1)
Filed a bug, this should not happen. (12183054)Lautrec
R
9

Try to hide navigation bar by SwiftUI explicitly, like

Form {

  // ... other code

}
.navigationBarTitle("")
.navigationBarHidden(true)
Retroversion answered 30/8, 2020 at 4:40 Comment(3)
Great! Thanks for this tip. Helped me a lot!Appease
Nope. That just doesn't work, at least with iOS 15.7. I'm going to file a bug. Embedded SwiftUI view should not control the visibility of its embedding view controller.Lautrec
Yeah, this works fine. But unfortunately not for iOS 15. @Lautrec did you find any solution for this?Whipstall
B
0

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 UITabBarController.

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.

enter image description here

Bertrando answered 22/11, 2021 at 18:34 Comment(0)
B
0

You should inherit UIHostingController, and then hide navigation bar in viewWillAppear:

class BasicInfoHostingController: UIHostingController<BasicInfo> {
    
    private var isHidingNav: Bool = false
    
    override func viewDidLoad() {
        super.viewDidLoad()
        isHidingNav = navigationController?.isNavigationBarHidden ?? true
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        navigationController?.setNavigationBarHidden(true, animated: false)
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        navigationController?.isNavigationBarHidden = isHidingNav
    }
}
Budweis answered 19/9 at 3:25 Comment(0)
C
-1
override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    setNavigationBarHidden(true, animated: false)
}

This works for me.

Catrinacatriona answered 10/1, 2023 at 5:18 Comment(3)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Faviolafavonian
This question is about SwiftUI and not UIKit. Recommend deletion.Rialto
This will produce a visible glich: the navigation bar will be displayed during the push animation, then hidden on animation stop.Lautrec

© 2022 - 2024 — McMap. All rights reserved.