8 votes

Impossible de masquer la barre de navigation lors de l'intégration de swiftUI dans UIkit

Je tente de masquer la barre de navigation en insérant du swiftUI à l'intérieur d'un UIViewController UIKit comme ceci :

override func viewWillAppear(_ animated: Bool) {
   super.viewWillAppear(animated)
   self.navigationController?.setNavigationBarHidden(true, animated: animated)

Mais elle ne disparaît pas. En revanche, quand j'enlève le swiftUI, ça marche. Est-ce que quelqu'un sait comment résoudre ce problème ?

Édition :

J'instancie une vue de cette manière let controller = UIHostingController(rootView:view()) où la vue est le swiftUI et ensuite j'ajoute cela à la UIView() comme vous le feriez avec n'importe quel élément UIKit.

5voto

TParizek Points 260

UIHostingViewController respecte la valeur navigationBarHidden de votre vue SwiftUI. Vous pouvez soit appeler .navigationBarHidden(true) à la fin de votre vue SwiftUI, soit utiliser la sous-classe personnalisée UIHostingController comme indiqué dans l'exemple ci-dessous.

Solution :

import SwiftUI
import UIKit

class YourHostingController : UIHostingController 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")
  }
}

Exemple d'utilisation:

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

4voto

Mika Points 81

Cacher la barre de navigation d'une classe qui étend UIHostingController semble fonctionner lorsque setNavigationBarHidden est appelé dans viewDidAppear au lieu de viewWillAppear.

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

3voto

Je suis tombé sur ce problème hier aussi.

Je présente un modal UINavigationController avec un UIViewController en tant que rootViewController, qui intègre une vue SwiftUI via UIHostingController.

Le fait de définir le setNavigationBarHidden habituel dans viewDidAppear du UIViewController cesse de fonctionner dès que la vue SwiftUI est intégrée.

Vue d'ensemble:

Root ViewController: setNavigationBarHidden dans viewWillAppear

Barre de Navigation Visible:
UINavigationController > root UIViewController > UIHostingController intégré

Barre de Navigation Invisible:
UINavigationController > root UIViewController > pas de UIHostingController

Après quelques tests de débogage, j'ai réalisé que le UIHostingController lui-même appelle à nouveau setNavigationBarHidden.

La raison de ce problème est donc que les UIHostingControllers modifient la UINavigationBar environnante de l'UINavigationController.

Une solution simple:

Définissez la propriété de la barre de navigation dans la première vue SwiftUI présentée qui est intégrée par votre UIHostingController.

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

Cela rétablira l'ajustement que SwiftUI et le UIHostingController tentent d'appliquer à votre UINavigationController environnant.

Comme il n'y a aucune garantie concernant l'interaction entre SwiftUI et UIKit (qu'il utilise UIKit sous-jacent), je recommanderais de garder le setNavigationBarHidden dans le viewDidAppear environnant avec ce modificateur également.

2voto

Wilson Muñoz Points 91

Je veux inclure mon approche ici au cas où quelqu'un la trouverait utile lorsqu'il travaille avec SwiftUI. J'ai découvert que le problème était que UIHostingController remplacait quelque chose dans ma déclaration de

navigationController?.setNavigationBarHidden(true, animated: false)

Alors j'ai simplement créé un UIHostingController personnalisé et utilisé viewWillAppear(_ animated:Bool):

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

Ensuite, lorsque vous ajoutez ce UIHostingController dans votre ViewController:

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

//Contraintes
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

0voto

Amir Khorsandi Points 608

Rien n'a fonctionné pour moi alors j'ai ajouté un observateur pour masquer navigationBar dans la vue parent :

    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
        }
    }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X