[Résolu] Un delegate perso dans un PageViewController

2»

Réponses

  • DrakenDraken Membre
    mai 2015 modifié #32

    Tu devrais faire un petit programme de test, pour te concentrer juste sur le problème, sans te soucier de ton application. Et nous montrer le code, ce sera plus facile à  comprendre, pour toi et pour nous. Quand je n'arrive pas à  faire quelque chose, j'écris une micro-application servant de plate-forme de test.


     


    Si tu arrives à  faire fonctionner un délégué dans un UIViewController en "solo", c'est peut-être que sa cible est self, donc lui-même. Dans un environnement multi-vue comme le tien, le délégué est peut-être un autre objet (hypothèse au doigt mouillé, sans regarder ton code d'un km de long). N'oublie pas que tu peux tester une variable? avant de l'utiliser avec l'opérateur "!" qui suppose qu'elle contient forcément quelque chose, et donc JAMAIS nil.



    var maVariable:Machin?
    ..
    ..
    // Test
    if (maVariable == nil) {
    println ("maVariable contient nil!!")
    } else {
    executerUneFonction(maVariable!)
    }

     

    ça évite le plantage en cas d'utilisation de maVariable! avec la valeur nil.


  • AliGatorAliGator Membre, Modérateur

    N'oublie que tu peux tester une variable? avant de l'utiliser avec l'opérateur "!" qui suppose qu'elle contient forcément quelque chose, et donc JAMAIS nil.


    var maVariable:Machin?
    ..
    ..
    // Test
    if (maVariable == nil) {
    println ("maVariable contient nil!!")
    } else {
    executerUneFonction(maVariable!)
    }

     
    ça évite le plantage en cas d'utilisation de maVariable! avec la valeur nil.

    C'est de toute façon une très mauvaise idée d'utiliser "!" sur une variable Optional, car comme tu le dis si bien Draken si cette variable contient "nil" le programme va planter. Et du coup même si avec ton code tu protèges ça par un "if", c'est dommage de finir par utiliser "!" quand même au lieu de profiter de l'Optional Binding.

    La bonne pratique à  prendre est donc de toujours utiliser l'Optional Binding (et comme ça si jamais un jour tu vois un "!" n'importe où dans ton code pour unwrapper un Optional, tu te dis que t'as fait quelquechose de mal):

    // var maVariableOptional : String?
    if let contenuNonNilDeMaVariable == maVariableOptional {
    executerUneFonction(contenuNonNilDeMaVariable)
    } else {
    println ("maVariableOptional contient nil!!")
    }
    Et en pratique une fois qu'on est habitué à  utiliser l'Optional Chaining, on ne s'embête pas systématiquement à  donner un nom différent pour la variable Optional et pour son binding non-Optional dans le "if let" :
    var maVariable : String? // (1)
    if let maVariable = maVariable {
    // Dans le contexte de ce block à  l'intérieur des accolades du if-let,
    // maVariable contient le contenu, non-nil, de la variable (1)
    // et est donc de type String dans ce contexte.

    // Exactement comme contenuNonNilDeMaVariable dans l'exemple précédent

    // En fait, ici, la variable "maVariable" créée par le "if let maVariable"
    // "masque"/"prend le dessus sur" la variable (1) de même nom de contexte plus global
    // (on dit "shadows the other variable" en anglais)
    executerUneFonction(maVariable)
    } else {
    // par contre ici comme n'importe où à  l'extérieur du bloc if-let
    // maVariable fait bien toujours référence à  (1)
    println("maVariable contient nil !")
    }
    Au moins, via cette syntaxe et cette convention de ne jamais utiliser "!" mais de toujours préférer l'Optional Binding, ça t'oblige à  faire le test pour savoir si ta variable est nil ou pas, ce qui est une bonne habitude pour bien penser à  traiter le cas nil et pour ne pas oublier et risquer de crasher.
  • Salut Lexxis, merci pour tes efforts.


     


    la variables delegateEtape1 est dans la partie "Variables" du code du contrôler Etape1ViewController



    var delegateEtape1: Etape1ViewControllerDelegate?

    Comme dans Etape0ViewController.



    var delegateEtape0: Etape0ViewControllerDelegate?

    En tout cas, j'ai un peu joué avec les breakPoints, chui pas un pro de tout ça, je galère un peu avec le debugger. J'ai pourtant lu plein de autos et vu quelques vidéos, mais il faudra bien que j'approfondisse tout ça.


     


    En attendant j'ai fait un :



    println("delegateEtape0 : \(delegateEtape0)")

    Et la sortie donne :



     


    delegateEtape0 : Optional(<GuideEsthetique.ContainerViewController: 0x78753550>)



     


    Et fait un :



    println("delegateEtape1 : \(delegateEtape1)")

    Et la sortie donne :



     


    delegateEtape1 : nil



     


    Très intéressant tout ça.


     


    Cela confirme les dires de tous les collègues. Vous avez raison.


     


    Maintenant, je ne vois pas trop comment faire autrement, puisque les deux delegate sont totalement identique, avec leur protocole, etc...


     


    Je vais essayé de travailler à  partir du post de Céroce de 17h34, mais j'avais déjà  essayé, sans succès.


    Je vais recommencer, en faisant cela tranquillement, sans stress.


     


    Merci à  tous.

  • Ah, désolé, Draken et AliGator, je n'avais pas vu vos posts très intéressant.


     


    Je m'y met de ce pas


     


    Grand merci.


  • busterTheobusterTheo Membre
    mai 2015 modifié #36

    Draken, j'ai fait comme tu m'as dit, et avec la technique de AliGator.


     


    Dans la première page de mon pageView :



    @objc protocol Etape1L1ViewControllerDelegate {
    optional func configureNavbar(etapeViewController: UIViewController)
    }

    Puis :



    var delegateEtape1L1: Etape1L1ViewControllerDelegate?

    Puis dans le viewDidLoad :



    if let delegateEtape1L1 = delegateEtape1L1 {
    delegateEtape1L1.configureNavbar?(self)
    println("delegateEtape1L1 = \(delegateEtape1L1)")
    } else {
    println("delegateEtape1L1 = nil")
    }

    Evidemment ça me renvoi nil, et donc ça marche pas


     


    J'ai également fait dans mon container général, là  ou se trouve ma méthode perso :



    class ContainerViewController: UIViewController, PatientsViewControllerDelegate, Etape0ViewControllerDelegate, Etape1L1ViewControllerDelegate {

    Puis dans le viewDidLoad :



    etape1L1ViewController.delegateEtape1L1 = self

    Et dans ce même container général, les méthodes



    // MARK: - UIPageViewControllerDelegate

    func pageViewController(pageViewController: UIPageViewController, willTransitionToViewControllers pendingViewControllers: [AnyObject]) {

    }

    func pageViewController(pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [AnyObject], transitionCompleted completed: Bool) {
    if !completed {
    return
    }
    }

    Et ma méthode perso :



    // NavBar
    func configureNavbar(etapeViewController: UIViewController) {

    etapeViewController.navigationItem.setHidesBackButton(true, animated: false)

    var fixedSpace:UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FixedSpace, target: nil, action: nil)
    fixedSpace.width = 36.0

    var addPatientsButton: UIBarButtonItem = UIBarButtonItem(image: UIImage(named: "addButton.png"), style: .Plain, target: self, action: "nouveauPatient")
    addPatientsButton.tintColor = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)

    var newPatientsButton: UIBarButtonItem = UIBarButtonItem(image: UIImage(named: "patientsButton.png"), style: .Plain, target: self, action: "togglePatients")
    newPatientsButton.tintColor = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)

    var buttonGoEtape2: UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Play, target: nil, action: "goEtape2")
    buttonGoEtape2.tintColor = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)

    etapeViewController.navigationItem.leftBarButtonItems = [fixedSpace, addPatientsButton, newPatientsButton, fixedSpace, buttonGoEtape2]

    println("configureNavbar - \(etapeViewController)")

    Ou est l'erreur ? o:)


  • colas_colas_ Membre
    mai 2015 modifié #37


    En tout cas, j'ai un peu joué avec les breakPoints, chui pas un pro de tout ça, je galère un peu avec le debugger. J'ai pourtant lu plein de autos et vu quelques vidéos, mais il faudra bien que j'approfondisse tout ça.


     




     


    Il faut que tu approfondisses ça le PLUS VITE possible. Crois-moi, le jour (arrivé trop tard) où je me suis au debugger, tout a été beaucoup plus simple.


     


    C'est simple.


     


    Tu mets un breakpoint. Puis tu explores pas à  pas ce que fait ton programme.


    cf.


  • busterTheobusterTheo Membre
    mai 2015 modifié #38

    Bon j'ai fait un truc qui marche, mais qui me semble carrément absurde, d'après ce que je croyais avoir compris.


     


    Vu que quand je faisais un :



    println("delegateEtape0 : \(delegateEtape0)")

    J'avais ça en sortie :



     


     


    delegateEtape0 : Optional(<GuideEsthetique.ContainerViewController: 0x78753550>)

    Bien que j'avais :



    var delegateEtape0: Etape0ViewControllerDelegate?

    J'ai donc essayer avec :



    var delegateEtape1: ContainerViewController?

    Puis :



    override func viewDidLoad() {
    super.viewDidLoad()

    delegateEtape1 = ContainerViewController()
    if let delegateEtape1 = delegateEtape1 {
    delegateEtape1.configureNavbar(self)
    println("delegateEtape1 = \(delegateEtape1)")
    } else {
    println("delegateEtape1 = nil")
    }
    }

    Et j'ai bien en sortie :



     


    delegateEtape1 = <GuideEsthetique.ContainerViewController: 0x7a24fa20>



     


    Donc pas nil - cool


     


    J'ai quand même gardé ça, sans quoi ça marche pas



    @objc protocol Etape1ViewControllerDelegate {
    optional func configureNavbar(etapeViewController: UIViewController)
    }

    Puis dans le container ou se trouve ma méthode perso :



    class ContainerViewController: UIViewController, PatientsViewControllerDelegate, Etape0ViewControllerDelegate, Etape1ViewControllerDelegate, Etape2ViewControllerDelegate, UIPageViewControllerDelegate {

    J'ai bien ma barre de nav qui s'affiche. C'est gagné pour le delegate dans le pageView, mais je ne comprend pas pourquoi - Bref.


     


     


    Mais maintenant, j'ai un pur soucis, les boutons de la barre de nav appellent bien leur action associée, mais elles ne fonctionnent pas. J'ai fait tout un tas de sortie println - et tout est pris - tout est bon, mais rien ne se passe. Curieux non ?


  • Merci Colas2 pour ton conseil.


     


    J'ai regardé les liens.

     


    J'ai joué avec tout ça, mais je ne comprend pas trop les messages affichés en bas, et parfois le code est remplacé par une page en chinois.


     


    En tout cas, c'est bien, mais faut pouvoir interprété.


     


    Moi, mon soucis c'est que les actions associées à  ma nav, ne fonctionnent qu'au début puis ensuite elles sont bien exécutées mais rien ne se passe. Et comme je n'ai pas de bug, le débuter ne m'aide pas trop



  • Et comme je n'ai pas de bug, le débuter ne m'aide pas trop




     


     


    En fait, le debugger est utile tout le temps pas que si tu as des bugs. ça permet de suivre le programme pas à  pas, pour voir ce qu'il fait, où il va. 


     


    Avec la commande



    po myObject.myProperty()

    tu peux même inspecter tes objets et voir, en live, ce qu'il y a dedans.

  • busterTheobusterTheo Membre
    mai 2015 modifié #41

    Bonjour à  tous,


    après 15 heures d'essais, j'ai enfin réussi à  faire fonctionner les méthodes de ma nav de gauche, dans les UIPageViewControllers.


    Celles issues de ce superbe  tuto.


    J'ai du reconsidérer tout un tas de truc, pour adapter la slideNav dans un pageView.


     


    Déjà , grâce à  tous vos conseils, j'ai beaucoup jouer avec les histoire de "nil" et de "?" et de "!".


    À l'aide de plusieurs println, j'ai pu isoler les sources du problème.


     


    Je ne m'étant pas là -dessus, si ce n'est que j'avais d'énormes doutes sur moi-même, mais ce matin, j'étais d'avantage guerrier et plein de confiance.


     


    En tout cas, une chose est certaine, ce qui a pu me sauver, est le fait d'avoir créer une classe externe dans laquelle j'y range tout un tas de méthodes et de variables utilisées tout au long de l'appli. En gros, merci au MVC, et donc à  vos explications et notamment le petit tuto perso de Draken.


     


    Et un autre truc que je trouve génial, c'est de pouvoir placer des variables au-dessus du début de création d'un UIViewController.


    Au-dessus de ça :



    class ContainerViewController: UIViewController, PatientsViewControllerDelegate, Etape0ViewControllerDelegate, Etape1ViewControllerDelegate, Etape2ViewControllerDelegate, UIPageViewControllerDelegate {

    Ce qui fait qu'elles sont toujours là  pour l'appli, même si le container n'est pas rechargé.


     


    Ah, comme disait, je ne sais plus qui, c'est le métier qui rentre.


     


    Je vais donc mettre un "Résolu", avec une énorme satisfaction, tout en sachant que je ne dois pas m'emballer, car,  j'imagine bien que j'aurai d'autres soucis par la suite.


     


    Dites moi, si je dépose du code, pour d'éventuels intéressés, et si oui, ne serait-il pas judicieux de créer un nouveau post "SlideNav dans un PageView", ou quelque chose comme cà .


     


    Donc, encore un grand merci, pour ce samedi qui commence bien.


     


    :p     :D   :p


  • Champagne !


  • Ouais, vraiment...


  • AliGatorAliGator Membre, Modérateur

    En tout cas, une chose est certaine, ce qui a pu me sauver, est le fait d'avoir créer une classe externe dans laquelle j'y range tout un tas de méthodes et de variables utilisées tout au long de l'appli. En gros, merci au MVC, et donc à  vos explications et notamment le petit tuto perso de Draken.

    Heu ne me dis pas que tu as fait un "Singleton fourre tout avec toutes les variables en vrac dedans" ? C'est pas très MVC ça au contraire... pratique je dis pas, acceptable, c'est déjà  + discutable (ça dépend du contexte de cette "classe externe dans laquelle tu range tout") mais MVC, pas trop si c'est un truc fourre-tout et en plus un Singleton. En général, l'idée c'est au contraire de faire des classes spécialisées, qui sont dédiées à  leur rôle, et surtout éviter les "classes à  tout faire" dans lesquelles tu mets un peu tout et n'importe quoi...

    Et un autre truc que je trouve génial, c'est de pouvoir placer des variables au-dessus du début de création d'un UIViewController.
    Au-dessus de ça :


    class ContainerViewController: UIViewController, PatientsViewControllerDelegate, Etape0ViewControllerDelegate, Etape1ViewControllerDelegate, Etape2ViewControllerDelegate, UIPageViewControllerDelegate {
    Ce qui fait qu'elles sont toujours là  pour l'appli, même si le container n'est pas rechargé.

    Ne me dit pas non plus que tu utilises des variables globales ? Placer des variables en dehors du contexte d'un objet, donc dans l'espace global (faisant ainsi des variables globales) est une très mauvaise idée et très mauvaise pratique, entre autres car c'est loin d'être thread-safe et que leur accès n'est pas contrôlé (je ne m'étend pas sur le sujet, j'en ai déjà  parlé à  plein plein de reprises partout dans le forum). Donc à  éviter si tu ne veux pas perdre des heures à  galéjer à  débuguer un truc qui serait à  cause par exemple d'un accès concurrent à  une variable globale (un des trucs les plus costaud à  débuguer, car c'est des bugs dus à  des "race conditions" donc difficiles à  reproduire).
  • Ah, AliGator, j'étais certain de ton retour. Génial, et merci.


     


    Je t'explique ce que j'y met, et tu me dis si c'est ok.


     


    Ma classe, c'est ça :



    class MyFunctions: NSObject, UIScrollViewDelegate {

    Dans laquelle, j'ai tout un tas de fonctions de fabrication de UIView/Layer, etc, commun à  tous mes écran (sauf le premier).


    Genre :



    func configBoxFilles(etapeViewController: UIViewController) {

    viewPorteuseFille1Etapes = UIView(frame: CGRectMake(92, 108, 560, 420))

    etc...


     


    Je ne pense pas que ça pose un problème, non ?


    Je ne vais quand même pas placer dans chacun de mes 150 controllers, 1000 lignes de codes de fabrication des fonds, etc, de surcroit, communs à  toutes mes vues.


    Je pense que tu seras d'accord, enfin j'espère.


     


    Ensuite, dans cette classe, les seules variables sont celles utilisées par la classe.


    Sauf celle-ci qui me permet que le bool de la nav de gauche soit toujours pris en compte, car le container général ne se recharge pas lorsque je change d'étape avec mon fameux delegate.



    // MARK: Gestion de la nav de gauche

    var etatCourantPanneaux: EtatPanneaux = .ToutCollapsed {
    didSet {
    let montrerOmbre = etatCourantPanneaux != .ToutCollapsed
    ombrePage(montrerOmbre)
    }
    }

    func ombrePage(montrerOmbre: Bool) {
    if (montrerOmbre) {
    pagesNavigationController.view.layer.shadowOpacity = 0.8
    } else {
    pagesNavigationController.view.layer.shadowOpacity = 0.0
    }
    }

    D'autre part, concernant mes variables "globale" dans le container général, je me rend compte que 98% d'entre elles devraient être dans la fameuse classe, car elles n'y sont utilisées que là .


    Donc, j'ai modifié tout cela, selon tes conseils, effectivement, elles n'ont rien à  faire là .


     


    Du coup, dans mon premier  controleur (enfin, mon premier écran), qui, lui, n'a pas de boites communes, mais de la même couleur, je dois faire appel à  la même variable de couleur



    // Couleur des boites blanches - box filles et mère
    var fondsColor = UIColor(red: 246/255, green: 246/255, blue: 246/255, alpha: 1.0)

    Et donc, j'y accède ainsi :



    viewOmbreVignetteFrontalPatient.backgroundColor = myFunctions.fondsColor

    Je pourrais effectivement, spécialement pour ce controller différent, ne pas appeler cette variable, et la créer localement.


    Qu'en penses-tu ?


     


     


     


    Par contre, j'en ai deux, qu'il me semble indispensable de laisser à  cette place :



    // Model
    var listeDesVariables = ListeDesVariables()

    // Fonctions generiques
    var myFunctions = MyFunctions()

    Tu comprends pourquoi.


     


    Et surtout une autre, et là , c'est capital pour, toujours cette satanée nav gérée par ce satané delegate.



    var pagesNavigationController: UINavigationController!

    Là , je suis certain que tes cheveux vont se isser sur ta tête d;-)


     


    Voilà , merci pour tes retours, toujours aussi précieux.

  • AliGator, je viens de lire tes explications ici, et je ne pense pas que ma classe soit un singleton. Car c'est juste des trucs de construction, de gesture sur ces boites construites, et de suppression de boites de l'affichage.


     


    Concernat le "sharedInstance", je n'ai pas compris ce que c'était.


     


    Je pense que c'est juste une classe qui lorsqu'elle est instanciée, ne crée rien. C'est ensuite, dans mes contrôler, que je déclenche les fonctions, qui elles, créent une boite, un rond, ou n'importe quelle connerie visuels sur un écran.


     


    Rien qui concerne le Model, ou d'éventuels calculs.


     


    Comment ça s'appelle une classe comme ça ?


     


    Un fourre-tout de fonctions (créatrice des fonds) communes ?


  • AliGatorAliGator Membre, Modérateur
    Si tu as une classe qui ne contient que des méthodes de création d'objets, ça s'appelle une Factory (bien que je t'invite à  regarder en détail le concept de Object Factory car c'est clairement défini comme concept, pas juste "truc qui crée des objets", ça respecte des règles)

    Si tu fais ça, c'est une bonne pratique à  condition que tes classes soient de vraies factory, pas une classe fourre-tout de création d'objets. Et d'avoir une Factory par type, de pas tout mettre dans une grosse Factory.

    Rappelle-toi qu'une bonne architecture en POO est en général bien segmentée de sorte que chaque classe ait sa propre responsabilité, il faut mieux avoir plusieurs classes qui ne font pas grand chose mais le font bien qu'une grosse classe qui fait tout.


    Concernant ta variable fondsColor, il n'y a aucune justification d'en faire une variable globale. Ce qui n'est pas bien dans les variables globales, c'est que n'importe qui (y compris n'importe quel thread) peut modifier la valeur, sans contrôle, et même alors qu'un autre thread est précisément en train de lire la valeur en cours d'être modifiée.

    Par contre, fondsColor est un très bon candidat pour être une constante (et non pas une variable). Et là  aucun souci pour qu'une constante soit globale (par contre histoire de respecter les conventions de nommage, on va la faire commencer par une majuscule). Au final tu as peut-être l'impression que juste remplacer ce "var fondsColor" par "let FondsColor" c'est pas un gros changement et que c'est pas si grave d'avoir mis un var au lieu d'un let, mais cela change beaucoup de choses, puisque cela t'éviter un paquet de bugs potentiels que tu aurais pu avoir avec le fait que ce soit une variable globale.
  • busterTheobusterTheo Membre
    mai 2015 modifié #48

    Ah, ok, merci.


     


    Pour fondColor, c'est dans la classe externe. Et je vais la mettre en let, t'as carrément raison, puisqu'elle ne changera jamais, c'est donc une constante. Négligence de ma part.


     


    Par contre, ais-je le droit, quand même de l'appeler, à  partir de mon premier controller (qui lui est différent de tous les autres), ainsi ?



    viewOmbreVignetteFrontalPatient.backgroundColor = myFunctions.fondsColor

    Puisque c'est effectivement une constante, mais pas globale, puisqu'utilisée que dans la classe externe (sauf sur le premier controller)


    Enfin, bref, je pense que je la met en constante dans la classe externe, et que dans le premier controller, je crée exceptionnellement une constante en local.


     


     


     


     



     


     


    Rappelle-toi qu'une bonne architecture en POO est en général bien segmentée de sorte que chaque classe ait sa propre responsabilité, il faut mieux avoir plusieurs classes qui ne font pas grand chose mais le font bien qu'une grosse classe qui fait tout.

     


    Donc, il vaut mieux que je fasse une classe qui fait un rond, une classe qui fait un carré, etc, plutôt qu'une classe qui fait tous mes ronds et mes carrés communs à  toutes mes vues ?


     


    Cela signifie que dans mes controllers, plutôt que de faire



    myFunctions.configBoxFilles(self)

    myFunctions.configNav(self)

    // Creation des outils
    myFunctions.configVolets()
    myFunctions.configPoignees()
    myFunctions.panGesturesPoignees()

    myFunctions.afficheOutils = true

    myFunctions.configFille2(self)

    Je devrais faire 



    myFunctions.configBoxFilles(self)

    configNavA.configNav(self)

    // Creation des outils
    configVoletsA.configVolets()
    configPoigneesA.configPoignees()
    panGesturesPoigneesA.panGesturesPoignees()

    afficheOutilsA.afficheOutils = true

    configFille2A.configFille2(self)

    Excuses pour les nommages, c'est pour aller vite


     


     


    à‰videmment, au préalable, j'instancierais



    var configVoletsA: ConfigVoletsA!

    Heu, j'ai un peu du mal à  comprendre, puisque pour moi, ma classe, justement, a sa propre responsabilité. Elle crée toujours les même trucs (carrés, bons, etc) sur toutes les vues.


     


     


    Et concernant cela ?



     


    Par contre, j'en ai deux, qu'il me semble indispensable de laisser à  cette place :


    // Model
    var listeDesVariables = ListeDesVariables()

    // Fonctions generiques
    var myFunctions = MyFunctions()

    Tu comprends pourquoi.


     


    Et surtout une autre, et là , c'est capital pour, toujours cette satanée nav gérée par ce satané delegate.


    var pagesNavigationController: UINavigationController!

    Là , je suis certain que tes cheveux vont se isser sur ta tête d;-)



     


    T'en penses quoi ?


  • AliGatorAliGator Membre, Modérateur

    Ma classe, c'est ça :


    class MyFunctions: NSObject, UIScrollViewDelegate {
    Dans laquelle, j'ai tout un tas de fonctions de fabrication de UIView/Layer, etc, commun à  tous mes écran (sauf le premier).
    Genre :

    func configBoxFilles(etapeViewController: UIViewController) {

    viewPorteuseFille1Etapes = UIView(frame: CGRectMake(92, 108, 560, 420))
    etc...
     
    Je ne pense pas que ça pose un problème, non ?

    Donc pour reprendre cet exemple là , non ça ça n'est pas propre.
    - Le fait que tu l'appelles "MyFunctions" déjà  laisse présager que c'est un fourre-tout, qui n'a pas une responsabilité claire mais est un peu classe-à -tout-faire.
    - Pourquoi, si c'est cette classe a pour but juste de créer ou configurer des objets (comme tes BoxFilles), doit-elle hériter de NSObject, et pire encore, pourquoi c'est elle qui est le UIScrollViewDelegate ? Si tu veux faire une classe qui est spécialisée pour t'aider à  juste créer tes boites, ça serait plus propre qu'elle ne fasse que ça. D'autant que la configuration d'une boite c'est quelque chose de global, qui ne dépend pas de la page, si j'ai bien compris, chaque page pour laquelle tu vas vouloir configurer tes BoxFilles utilisera les mêmes fonctions, et sera stateless (ne dépendra pas d'un état d'un objet, comme "est-ce que la page est dans tel ou tel état ?", mais est une configuration "globale". Donc ça n'a pas forcément de nécessité d'être une méthode d'instance, qui dépend de l'instance en question, ça peut être une fonction globale ou au moins une méthode de classe
    - D'ailleurs pourquoi du coup faire une classe ici, alors que soit des fonctions globales pourraient aller (mais ça fait un peu fouillis de les mettre dans le namespace global, je suis d'accord), soit une struct pourrait faire l'affaire (puisqu'en Swift les struct peuvent avoir des fonctions) ? Genre "struct BoxConfigurator" avec des "static func configBoxFilles(...)" et tu appelles ça "BoxConfigurator.configBoxFilles(...)" en passant la boite à  configurer, par exemple.
    - Ou sinon tu peux aussi prévoir une "BoxFactory", qui te retourne une boite toute pré-configurée quand tu en as besoin
    - Et pour ce qui est du UIScrollViewDelegate, c'est une autre responsabilité, donc moi je ferai une autre classe, séparée


    Bon, après, ce ne sont que des idées en vrac, qui en fait ne sont peut-être pas les plus adaptées à  ton code, car je ne connais pas ton contexte, il faudrait que je me pose et prenne le temps de regarder ton code et ton projet, mais ce sont des pistes.

    Je ne vais quand même pas placer dans chacun de mes 150 controllers, 1000 lignes de codes de fabrication des fonds, etc, de surcroit, communs à  toutes mes vues.
    Je pense que tu seras d'accord, enfin j'espère.

    C'est à  ça que sert le patter Factory, à  avoir une classe dédiée à  la fabrication d'objets. Tu as des Abstract Factory (ce qui est moins ce qui correspond à  ton contexte) et des Object Factory (ça c'est + pour ton cas, création d'objets pré-configurés).


    Ensuite, dans cette classe, les seules variables sont celles utilisées par la classe.
    Sauf celle-ci qui me permet que le bool de la nav de gauche soit toujours pris en compte, car le container général ne se recharge pas lorsque je change d'étape avec mon fameux delegate.


    // MARK: Gestion de la nav de gauche

    var etatCourantPanneaux: EtatPanneaux = .ToutCollapsed {
    didSet {
    let montrerOmbre = etatCourantPanneaux != .ToutCollapsed
    ombrePage(montrerOmbre)
    }
    }

    func ombrePage(montrerOmbre: Bool) {
    if (montrerOmbre) {
    pagesNavigationController.view.layer.shadowOpacity = 0.8
    } else {
    pagesNavigationController.view.layer.shadowOpacity = 0.0
    }
    }

    Là  j'ai pas trop compris, c'est une variable globale à  l'extérieur de ton ViewController, ça ?

    D'autre part, concernant mes variables "globale" dans le container général, je me rend compte que 98% d'entre elles devraient être dans la fameuse classe, car elles n'y sont utilisées que là .
    Donc, j'ai modifié tout cela, selon tes conseils, effectivement, elles n'ont rien à  faire là .

    Ca me rassure que tu aies pu les mettre en propriété à  l'intérieur de la classe, mais ça me pose quand même question ta phrase, car une variable globale est commune à  toutes les instances, alors qu'une propriété est propre à  chaque instance (sauf si tu fais des variables de classe, mais tu n'as pas précisé ce point). Donc si t'as juste fait un copier/coller pour les déplacer telles qu'elles à  l'intérieur du "class ... { }", c'est pas la même chose que tu as obtenu...

    Par contre, j'en ai deux, qu'il me semble indispensable de laisser à  cette place :


    // Model
    var listeDesVariables = ListeDesVariables()

    // Fonctions generiques
    var myFunctions = MyFunctions()
    Tu comprends pourquoi.

    Heu non, pas vraiment. Je ne comprends pas pourquoi ces éléments sont des "var" et pas des "let", je ne comprend pas pourquoi tu as besoin de ListeDesVariables() " ça fait un peu fourre-tout, là  encore, mais surtout je ne vois pas pourquoi tu as besoin de variables qui ne sont pas rattachées à  une instance, et faire ça revient finalement un peu au même que de faire des variables globales, donc ça ne fait que déplacer le problème.

    Et surtout une autre, et là , c'est capital pour, toujours cette satanée nav gérée par ce satané delegate.


    var pagesNavigationController: UINavigationController!
    Là , je suis certain que tes cheveux vont se isser sur ta tête d;-)

    Je confirme, j'ai presque fait une crise cardiaque. 
  • AliGatorAliGator Membre, Modérateur

    Donc, il vaut mieux que je fasse une classe qui fait un rond, une classe qui fait un carré, etc, plutôt qu'une classe qui fait tous mes ronds et mes carrés communs à  toutes mes vues ?

    Alors non, peut-être pas à  ce point d'avoir un truc pour les Ronds et un truc pour les Carrés (à  vrai dire j'ai du mal à  savoir ce que tu veux faire, car j'ai pas pris le temps de lire tout ton code plus haut et surtout je ne sais pas à  quoi ressemble ton application, mais bon).

    Ca ne me choque pas que tu fasses une Factory qui contiennent à  la fois les méthodes pour créer des Ronds mais aussi celles pour créer des Carrés " pas non plus besoin d'avoir forcément une Factory pour les ronds et une autre pour les Carrés.

    Par contre ce qui ne me parait pas cohérent c'est d'avoir une classe qui à  la fois crée les Ronds ou les Carrés, mais est aussi UIScrollViewDelegate, et fait aussi d'autres choses qui n'ont rien à  voir avec la création des Ronds ou Carrés.

    Excuses pour les nommages, c'est pour aller vite

     
    Je pense que ça fait aussi partie du problème.
    Le fait que tu aies nommé ça "MyFunctions" me gène car pour moi ça veut dire que tu mets tout et n'importe quoi dedans.

    Je verrais plutôt une classe (ou même une struct, pour le coup) qui s'appelle "ShapeFactory", et qui a pour seule responsabilité de te créer tes Ronds et tes Carrés. Et ensuite une autre classe (ou struct) qui elle se chargerait de la partie UIScrollViewDelegate, si vraiment tu utilises le même code de UIScrollViewDelegate pour des UIViewController totalement différents et que tu as besoin de mettre du code commun à  un endroit. Mais pas dans le ShapeFactory, ce n'est pas son rôle.
  • AliGatorAliGator Membre, Modérateur
    Et ceci dit tout ceci étant dit, si vraiment tes UIViewContollers ont tant de chose que ça en commun, comme la création de boites, les implémentations de UIScrollViewDelegate, et tant d'autres choses... pourquoi ne pas simplement tous les faire hériter d'un UIViewController parent ? T'aurais peut-être dû commencer par ça (ou par nous expliquer pourquoi d'après toi tu ne peux pas faire ça dans ton contexte) ?
  • Oups, je vais prendre le temps de tout relire plusieurs fois avant de répondre.


    J'ai à  peu-près tout compris, et je suis évidemment d'accord avec toi sur tous les points.


    Je vais donc me retrouver confronté à  de nouveaux problèmes, mais c'est pour la bonne cause. J'y crois fort.Un grand merci encore.


     


    Merci pour tes efforts.


     


    Donc, mon truc, enfin, mes trucs, ça sent un peu la poudre. Mince... Allez, au boulot :p


  •  


     


    Et ceci dit tout ceci étant dit, si vraiment tes UIViewContollers ont tant de chose que ça en commun, comme la création de boites, les implémentations de UIScrollViewDelegate, et tant d'autres choses... pourquoi ne pas simplement tous les faire hériter d'un UIViewController parent ? T'aurais peut-être dû commencer par ça (ou par nous expliquer pourquoi d'après toi tu ne peux pas faire ça dans ton contexte) ?

     


     


    Ouais, je vais creuser ça aussi. Merci.


     


     


    Ben chui pas rendu, du coup...


  • AliGatorAliGator Membre, Modérateur
    En fait si ça se trouve depuis le début plutôt que de partir dans une solution alambiquée, il te suffisait de créer une classe parente de ton UIViewController dans laquelle tu mettais tout ton comportement et tes méthodes utilitaires communes à  tous ces UIViewControllers que tu comptais utiliser en page fille, et c'était fini...

    J'ai l'impression qu'on est allé un peu loin en explication tout ça parce qu'on pensait que t'avais déjà  essayé ça et que tu avais des besoins plus spécifiques, alors que cette solution de base t'aurait amplement suffit mais que tu n'y a juste pas pensé, tellement tu avais la tête dans le guidon...
  • busterTheobusterTheo Membre
    mai 2015 modifié #55

     


     


    tellement tu avais la tête dans le guidon...

    Où plutôt un petit vélo dans la tête  ::)  :D


  • Bonjour à  tous,


    après plusieurs semaines d'absence, je viens pour mettre résolu.


     


    J'ai à  peu près fait tout ce que vous m'avez recommandé.


     


    Encore merci.


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