Set d'une variable à  l'instanciation d'un controller

StephSteph Membre
décembre 2017 modifié dans Dev. iOS, watchOS, tvOS #1

Salut tout le monde,


 


Je suis toujours en mode prise de repère après mes 4 ans sans dev lol


 


Bref, dans l'app que je développe il y a un système d'onglet qui permet de switcher entre 3 tableView. Pour gérer les onglet j'ai utilisé un pod (TabPageViewController) qui fait ça très bien.


 


Les controllers sont déclarer comme ça :



let vc1 = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "InfosallViewController")
let vc2 = UIViewController()
let vc3 = UIViewController()

Ensuite on les ajoute à  TabPageViewController en faisant :



tabPageViewController.tabItems = [(vc1, "TOUT"), (vc2, "CAT1"), (vc3,"CAT2")]

Etant donné que les données à  afficher proviennent de CoreData, plutôt que de faire 3 TableViewController différents, je me suis dis, pourquoi ne pas instancier 3 fois le même mais en lui passant une variable pour indiquer quelle catégorie afficher et faire mon fetch en fonction.


 


Mais voila, je bloque, comment lui passer ce param ?


 


J'ai une class pour gérer ma tableView, j'ai bien tenter un var catToDisplay = "" mais on y accède pas en faisaint vc1.catToDisplay ce qui me parait normal. Vue qu'il s'agit d'un addSubview, je n'ai pas de non plus de segue sur lequel m'appuyer.


 


Bref, vos idées sont les bienvenues, j'aimerai autant ne pas faire 3 tableView avec 3 classes, c'est pas très propre.


 


Thanks


Réponses

  • CéroceCéroce Membre, Modérateur
    Le problème avec les UIViewControllers est que comme ils sont initialisés par la méthode initWithCoder() quand ils proviennent du storyboard/xib, on ne peut pas leur passer de paramètres à  l'init.
     
    La solution classique est de les passer dans des propriétés comme tu pensais le faire:


    class InfosallViewController: UIViewController {
    var categoryName: String!

    override func viewDidLoad() {
    assert(categoryName != nil)

    ...
    }
    }
    Quand tu instancies le VC depuis le Storyboard, il est de type UIViewController. Il faut donc le caster:

    let vc1 = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "InfosallViewController") as InfosallViewController
    Autrement, comme UIViewController n'a pas de propriété 'categoryName', tu ne pourras pas la passer.
  • Je test ça :)


     


    Merci @Céroce !


  • Bon en fait j'ai fais le boulet,


     


    j'ai déclaré mes VC comme suit : 



    let vc2 = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "InfosallViewController") as! InfosallViewController
    vc2.categoryName = "results"

    ça marche très bien, sauf que boulet que je suis, là  dedans je n'ai pas embarqué de NavigationController ce qui pose problème pour pousser une vue à  la sélection d'un cell.


     


    J'ai bien tenté un truc du genre (pas taper), mais ça marche pas lol


     




    let vc1 = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "infosNavController")
    let childController  = vc1.navigationController?.viewControllers[0] as! InfosallViewController
    childController.categoryName = "all"

    ça compile mais ça crash, forcément ...


  • Ton code crash, mais pour quelle raison ? Quel est le message d'erreur ?



    let navVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "infosNavController")
    let infoVC = navVC.topViewController as InfosallViewController
    infoVC.categoryName = "all"

    ?


     


    On est d'accord que dans ton Storyboard appelé Main.storyboard, le ViewController identifié infosNavController embed bien un InfosallViewController ?



  • Ton code crash, mais pour quelle raison ? Quel est le message d'erreur ?


     


    On est d'accord que dans ton Storyboard appelé Main.storyboard, le ViewController identifié infosNavController embed bien un InfosallViewController ?




     


    Un bad intructions, en fait, il fallait que je fasse ça :


     




    let vc1 = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "infosNavController") as! UINavigationController
    let childController  = vc1.viewControllers.first as! InfosallViewController
    childController.categoryName = "all"

    le topViewController doit passer aussi je pense, je vais tester :)





  • override func viewDidLoad() {
    assert(categoryName != nil)
    }



     


    Petite question, à  la construction du build final, le compilo vire les assert ou non ?


  • Ah oui en effet, je n'avais pas fait gaffe :



     let childController = vc1.navigationController?.viewControllers[0] as! InfosallViewController

    vc1 est déjà  un UINavigationController, donc il n'a pas de raison que `vc1.navigationController` retourne quelque chose de valide.


    Et donc le "!" à  la fin devrait causer le crash.


     


    La correction la plus basique serait donc:



    let childController = vc1.viewControllers[0] as! InfosallViewController

    Et tu peux donc utiliser .first



    let childController  = vc1.viewControllers.first as! InfosallViewController


     


  • CéroceCéroce Membre, Modérateur
    décembre 2017 modifié #9


    Petite question, à  la construction du build final, le compilo vire les assert ou non ?




     


    Oui, d'après ce que j'ai pu lire et constater, les assertions ne sont évaluées qu'en mode Debug.


     


    Edit: en fait, c'est subtile, mais pour assert(), la réponse est tout à  fait affirmative.


    http://blog.krzyzanowskim.com/2015/03/09/swift-asserts-the-missing-manual/


Connectez-vous ou Inscrivez-vous pour répondre.