web-dev-qa-db-fra.com

Écran noir après avoir présenté le contrôleur de vue modale dans le contexte actuel de UITabBarController

Mon contrôleur de vue racine est un UITabBarController. J'essaie de présenter un contrôleur de vue modale sur l'un des contrôleurs de vue du contrôleur de la barre d'onglets, mais j'autorise toujours l'utilisation de la barre d'onglets pour accéder à un autre onglet - en d'autres termes, j'aimerais que le modal interrompe uniquement pour le flux de cet onglet particulier, pas l'ensemble de l'application.

Pour ce faire, j'ai défini le style de présentation du contrôleur de vue de présentation sur "Sur le contexte actuel" dans le storyboard. Le problème que je rencontre est qu'après avoir présenté le contrôleur de vue modale et sélectionné un nouvel onglet, la vue du contrôleur de vue présenté est supprimée de la fenêtre et n'est pas ajoutée à la fenêtre lors de la fermeture du contrôleur de vue présenté. Après avoir fermé le contrôleur de vue, le déplacement vers un autre onglet, puis le retour remettent finalement le contrôleur de vue de présentation dans la fenêtre.

J'ai reproduit mon problème en utilisant le modèle 'Tabbed' dans Xcode.

Après avoir présenté le modal - j'ai ajouté de la transparence au contrôleur de vue présenté pour voir facilement ce qui se passe dans le contrôleur de vue présenté.

Passer au deuxième onglet, puis revenir - la vue du contrôleur de vue de présentation a maintenant été supprimée. 

Le rejet du modal laisse le contrôleur de vue de présentation avec sa vue toujours supprimée de la fenêtre. Aller à l'onglet 2 et revenir ajoute la vue à la fenêtre. 

J'espère que c'est quelque chose de simple que j'ai négligé dans le storyboard, mais le fait que je puisse présenter le modal et voir le contrôleur de vue présenté derrière lui avant de changer d'onglet me fait penser que les choses sont correctement configurées.

41
alivingston

J'ai eu le même problème et j'ai pu le résoudre en définissant self.definesPresentationContext = YES; sur le contrôleur de vue de présentation avant de présenter le VC modal. Vous pouvez également définir cela dans un storyboard, la case à cocher est appelée "Définit le contexte" dans Interface Builder.

36
Ole Begemann

Essayez de définir votre style de présentation sur "En plein écran" au lieu de "Sur le contexte actuel" dans le storyboard. enter image description here

13
malajisi

iOS 10+ et Swift 3 +

J'ai une très bonne solution à ce problème. L'utilisation, sur un style de présentation modale plein écran pour un contrôleur de vue, est présentée.

let storyboard = UIStoryboard(name: "Main", bundle: nil)  // Replace “Main” with your storyboard name

if let viewController = storyboard?.instantiateViewController(withIdentifier: “viewController Identifier”) as? ViewController {
            viewController.modalPresentationStyle = .overFullScreen
            self.present(viewController, animated: false, completion: { 
            })
        }

En plein écran, votre contrôleur de vue sera présenté au-dessus de votre barre d'onglets (contrôleur) en le couvrant. Ainsi, l'utilisateur final ne peut pas changer les éléments de la barre de tabulations (sauf si vous effectuez une opération par programmation). L'utilisateur doit fermer ce contrôleur de vue pour changer de barre d'onglets.

Si vous utilisez segue, pour présenter le contrôleur de vue, sélectionnez 'Over Full Screen' dans le style de présentation modale dans l'inspection des attributs

13
user7620770

Essayez de présenter le contrôleur de vue dans la fenêtre d'application. J'ai eu un problème similaire qui a été résolu par le code ci-dessous:

    let myNewVC = mainStoryBoard.instantiateViewController(withIdentifier: "MyNewVCId") as! MyNewVC
    let navController = UINavigationController(rootViewController: myNewVC)
    navController.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext    

    let appDelegate = UIApplication.shared.delegate as? AppDelegate
    appDelegate?.window?.rootViewController?.present(navController, animated: true, completion: nil)

J'espère que ça va t'aider aussi.

6
Shobhit C

j'ai eu ce problème: lorsque je présente mon ModalController, il prend un arrière-plan transparent et lorsque j'ai changé l'onglet en suivant dans tabBarController et getBack en précédent, l'arrière-plan transparent a disparu et il y a un mauvais arrière-plan noir après la recherche, j'ai trouvé le point le le point est le suivant:

self.definesPresentationContext = true

l'auto n'est pas le contrôleur modal l'auto est celui qui présente le contrôleur pour modalController et un autre point est .overCurrentContext comme celui-ci

** self.definesPresentationContext = true ** modalController.modalPresentationStyle = .overCurrentContext self.present(modalController, animated: true, completion: nil)

5
jamal zare

J'ai reproduit votre problème et trouvé une solution. Cela n'implique pas de changer la méthode de transition ni de modifier certains attributs dans le storyboard.

Suggestion:

Cela dit, voici une solution que je propose.

Solution:

Dans la méthode "viewWillDisappear" de votre ViewController présenté de façon modale, ajoutez ceci.

- (void)viewWillDisappear:(BOOL)animated {
    [self dismissViewControllerAnimated:true completion:^{
    [super viewWillDisappear:animated];
  }];
}
5
saugat gautam

Ayant un problème similaire avec mon contrôleur de tabulation, mais comme les commentaires, je suggère de changer la séquence en Push ou en séquence. Cela permettra à cet onglet de rester en contact avec la nouvelle vue affichée à la place de l'ancienne vue lors du passage à d'autres onglets. Si l'esthétique est un problème, vous pouvez créer un contrôleur de navigation personnalisé pour personnaliser l'apparence de la nouvelle vue.

1
Will Von Ullrich

J'ai le même problème dans le projet Swift. Live. J'ai déjà contourné ce problème.

Enfin, j'ai utilisé NSNotificationCenter et je rejette ce contrôleur de vue lorsque l'onglet est modifié pour résoudre ce problème.

J'ai référencé le contrôleur de la barre d'onglets dans AppDelegate et y ai défini délégué.

let storyboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)

let tabbarcontroller = storyboard.instantiateViewControllerWithIdentifier("MyTabBarController") as! UITabBarController

tabbarcontroller.delegate = self

Et c'est délégué comme

//MARK: - Tabbar controller delegate

extension AppDelegate : UITabBarControllerDelegate {

    func tabBarController(tabBarController: UITabBarController, didSelectViewController viewController: UIViewController) {

        NSNotificationCenter.defaultCenter().postNotificationName("TabBarTabChanged", object: nil)
    }
}

Ensuite, j'ai ajouter un observateur dans mon contrôleur de vue présenté comme

override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(PreviewPlaceVC.BackClickAction(_:)), name: "TabBarTabChanged", object: nil)
}

// MARK: - Button Click Actions

@IBAction func BackClickAction(sender: AnyObject) {
     self.dismissViewControllerAnimated(true, completion: nil)
}

Et ça marche bien pour moi. Ce n'est pas une bonne solution, je pense, pour rejeter le contrôleur de vue lors d'un événement de changement d'onglet, mais il est correct de rejeter plutôt que l'écran noir qui rompt également la navigation à ce moment-là.

0
Max