web-dev-qa-db-fra.com

Comment obtenir le contrôleur de vue précédent qui a poussé ma vue actuelle

La page d'accueil de mon application contient UIButtons, btnIncome et btnExpense. Un appui sur ce bouton pousse respectivement IncomeVC et ExpenseVC, qui sont deux UIViewControllers avec UITabBar ajouté via xib. Le tabbar contient 4 éléments. La sélection sur chaque élément d'onglet ajoute les mêmes quatre contrôleurs de vue (contenant UITableViews) que les sous-vues de IncomeVC et ExpenseVC, comme par exemple DailyVC, WeeklyVC, MonthlyVC, YearlyVC. Dépense) (j'ai fait comme ça parce que les IncomeVC et ExpenseVC ont un UIButton et un UIView qui est commun pour tous les onglets). 

Le problème est donc que, si vous cliquez sur la variable btnIncome, je dois renseigner ces vues de table avec les tableaux liés à Revenu et inversement pour Dépenses. Comment puis-je trouver à partir de quel viewController j'ai sélectionné les différents onglets (je dois l'obtenir à partir des 4 vues que j'ai ajoutées en tant que sous-vue de IncomeVC et ExpenseVC). Dois-je faire 8 vues différentes 4 chacune pour le revenu et les dépenses? Merci.

32
Midas

Si la raison pour laquelle vous avez besoin d'accéder au contrôleur de vue précédent est de savoir quelles données doivent être obtenues, nous vous suggérons plutôt de lui donner les données avant de le placer dans la pile. Ou au moins suffisamment de données pour que le contrôleur de vue sache comment obtenir les bonnes données, par exemple. une enum ou constante ou quelque chose. 

Cela peut être fait avec un initialiseur personnalisé ou une propriété . Jetez un coup d'œil à cet article de blog pour un exemple: "Passing Data Between View Controllers"

Si vous utilisez un storyboard, vous pouvez utiliser prepareForSegue:sender pour transmettre les bonnes données. Un bon tutoriel sur ce sujet peut être trouvé ici: Début des Storyboards dans iOS 5 Partie 2

7
Vegar

Vous pouvez obtenir le précédent viewController comme le code suivant,

NSLog(@"%@",[self.navigationController.viewControllers objectAtIndex:self.navigationController.viewControllers.count-2]);

Cela affichera le nom de viewController précédent ...

35
Venk

Dans Swift 3 ,

if let navController = self.navigationController, navController.viewControllers.count >= 2 {
     let viewController = navController.viewControllers[navController.viewControllers.count - 2]
}
25
Venk

Dans Swift :

let n: Int! = self.navigationController?.viewControllers?.count
let myUIViewController = self.navigationController?.viewControllers[n-2] as! UIViewController
20
King-Wizard

Swift 3

Voici un mashup des réponses précédentes qui peuvent être mis dans une extension:

extension UIViewController{
   var previousViewController:UIViewController?{
        if let controllersOnNavStack = self.navigationController?.viewControllers, controllersOnNavStack.count >= 2 {
            let n = controllersOnNavStack.count
            return controllersOnNavStack[n - 2]
        }
        return nil
    }
}

Modifier:

Lorsque vous extrayez la previousViewController d'un contrôleur de vue donné, appelez-le VC1, dans viewWillDisappear, VC1 est déjà sorti de la pile du contrôleur de navigation. Ainsi, dans ce scénario, le code ci-dessus ne récupère pas le contrôleur de vue directement au-dessus de VC1 (appelez-le VC2), mais le contrôleur de vue supérieur à VC2 (s'il existe).

Pour éviter ce problème, je vérifie juste si VC1 est toujours sur la pile quand previousViewController est demandé. Voici le code mis à jour:

extension UIViewController{
    var previousViewController:UIViewController?{
        if let controllersOnNavStack = self.navigationController?.viewControllers{
            let n = controllersOnNavStack.count
            //if self is still on Navigation stack
            if controllersOnNavStack.last === self, n > 1{
                return controllersOnNavStack[n - 2]
            }else if n > 0{
                return controllersOnNavStack[n - 1]
            }
        }
        return nil
    }
}

Ce code suppose que le contrôleur de vue auquel vous envoyez le message previousViewController sera soit en haut de la pile de navigation, soit pas du tout.

7
J.beenie
UIViewController *previousViewController = [[[self navigationController]viewControllers] objectAtIndex:([viewControllers indexOfObject:self]-1)];

Où self sera le contrôleur de vue actuel.

4
Zaraki

Swift 4.1, 4.2

 let allPreviousViewC = currentViewController.navigationController?.viewControllers // will give array of all pushed VC
// Can use if condition to check array count and then put below code inside that condition
    for viewC in allPreviousViewC! {
           print("ViewC is \(viewC)")
      }
1
GSK

Rapide

extension UINavigationController {
    func getPreviousViewController() -> UIViewController? {
        let count = viewControllers.count
        guard count > 1 else { return nil }
        return viewControllers[count - 2]
    }
}
1
dimpiax

Découvrez cet article: Comment identifier le contrôleur de vue précédent dans la pile de navigation Tony a raison, vous pouvez obtenir le précédent VC à partir du tableau viewControllers mais à l'index n-2.

0
CharlieReed

Vous pouvez certainement réutiliser les contrôleurs de vue. Je suggérerais au lieu de pousser UIViewController (qui contient UITabBar ajouté depuis IB) lorsque le bouton est enfoncé, vous pouvez pousser UITabBarController qui contient 4 contrôleurs de vue (quotidien, hebdomadaire, mensuel et annuel). 

UITabBarController pourrait avoir une propriété enum (revenus et dépenses), qui peut être attribuée lorsque vous appuyez sur ce UITabBarController en fonction du bouton enfoncé. À partir de là, vous pouvez affecter une autre propriété enum (Revenus et dépenses) aux 4 UIViewControllers afin d'afficher le type de données correct dans chaque contrôleur de vue.

0
Valent Richie