[Résolu] Un delegate perso dans un PageViewController

busterTheobusterTheo Membre
juillet 2015 modifié dans API UIKit #1

Bonjour,


mon soucis est que je ne parviens pas à  exécuter une fonction qui se trouve dans mon container général, à  partir d'un UIPageViewController.


 


Alors que j'y arrive très bien à  partir d'un simple UIViewController.


 


Voici ma fonction :


 


Il s'agit de faire une barre perso, qui soit partout la même



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

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

println("configureNavbar - \(etapeViewController)")
}

Lorsque j'appelle cette fonction, à  partir de mon UIViewController (Etape0ViewController), à  l'aide de :



delegateEtape0?.configureNavbar?(self)

dans le viewDidLoad (ou autres, d'ailleurs), ça fonctionne parfaitement.


 


Lorsque j'appelle la fonction à  partir de Etape1ViewController (qui est le controller maà®tre des sous-pages du UIPageViewController), la fonction n'est pas appelée.


 


J'ai essayé de placer l'appel de la fonction, dans tous les ViewControllers (maitre, sous-page, et classe de référence - le fameux content), et rien n'y fait.


 


Si quelqu'un a une idée, parce que là , je suis carrément bloqué, ça fait trois jours que je tourne en rond.


Merci d'avance.


«1

Réponses

  • C'est vraiment un truc tordu.


     


    J'ai même essayé de placer mon appel de fonction à  la création des controllers.



    unc populateControllersArray() {
    for i in 0...4 {
    let controller = storyboard!.instantiateViewControllerWithIdentifier("Etape1SbLevel\(i+1)") as ContentEtapesViewController
    controller.itemIndex = i
    delegateEtape1?.configureNavbar?(controller)
    controllers.append(controller)

    }
    }

    Et rien ne se passe. Pfff.


  • AliGatorAliGator Membre, Modérateur
    Et bien sûr tu as regardé s'il y avait pas un des Optionals qui n'était pas nil, et qu'il implémentait bien la méthode ?


    Car quand tu fais "delegateEtape1?.configureNavbar?(controller)" la méthode n'est appelée :
    - Que si "delegateEtape1" n'est pas nil (c'est pour ça que tu écris "?." pour dire "s'il n'est pas nil, appelle configureNavBar", c'est ça que veut dire cette syntaxe)
    - Que si la méthode congigureNavBar est implémentée (c'est pour ça que tu écris un point d'interrogation dans "configureNavbar?(controller)", pour dire "appelle la méthode si la méthode existe" (certainement car dans ton protocole tu l'as mis en "optional" ce qui fait qu'elle peut tout à  fait ne pas être définie dans l'objet que tu as dans ta variable "delegate1")
  • Ok, merci AliGator pour tes remarques.


     


    Je t'avoue que ces histoires de optionnal, de "?", et de "!", ça me saoule un peu, mais bon, il faudra bien qu'un jour je comprenne vraiment.


     


    En attendant, j'ai fait ça, et tout un tas de bidouilles autour de ce truc, et ça ne fonctionne pas.


     


    J'ai viré le "optionnal" de la méthode dans le protocole



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

    Je crée mon delegate



    var delegateEtape1: Etape1ViewControllerDelegate!

    Et j'appelle la méthode



    delegateEtape1?.configureNavbar(self)

    Et ça ne fonctionne pas


     


    J'ai essayé toutes les combinaisons possibles...


     


    Je fais comme là , par ex.


     


     


    Ma façon de faire (avec optionnal) fonctionne parfaitement à  partir d'un simple controller, donc je ne m'explique pas pourquoi elle ne fonctionne pas dans le cas d'un PageView.


     


    ça, c'était un essai à  la création des pages



     


     


    delegateEtape1?.configureNavbar?(controller)

     


    Mais, si je fais comme dans le cas d'un simple controller, c'est dans le viewDidLoad, et c'est ainsi que ça fonctionne



    delegateEtape1?.configureNavbar(self)

    Mais là , rien n'y fait.


     


     


    Quand tu dis



     


     


    c'est pour ça que tu écris un point d'interrogation dans "configureNavbar?(controller)

     


    Je comprend, et je supprime le "optionnal" et le "?"


     


    Mais quand tu dis



     


     


    Que si "delegateEtape1" n'est pas nil (c'est pour ça que tu écris "?." pour dire "s'il n'est pas nil, appelle configureNavBar"

     


    Alors là , je comprend rien


     


    J'essaie ça



    var delegateEtape1: Etape1ViewControllerDelegate = Etape1ViewControllerDelegate()

    ou ça



    var delegateEtape1 = Etape1ViewControllerDelegate() 

    ça déconne


     


     


    à‰videmment en adaptant l'appel de la fonction



    delegateEtape1.configureNavbar(self)

    ou

    delegateEtape1?.configureNavbar(self)

    ou

    delegateEtape1!.configureNavbar(self) 

    Enfin bref, j'y comprend rien, mais ça fonctionne dans un simple controller et pas dans un pageView


     


    Merci pour tes précisions, mais je suis carrément dégouté par ce truc.


    ça doit être mon côté codeur de base autodidacte.


    Je suis pourtant plutôt matheux, et j'adore les concepts, mais là , je suis bluffé. Peut-être un peu trop présomptueux sur mes compétences.


     


    Si t'as une autre idée, je suis preneur. Merci

  • busterTheobusterTheo Membre
    mai 2015 modifié #5

    Concernant les déclarations, je fais ça



    var viewFille2Etapes1: UIView!

    Puis dans le viewDidLoad (ou autre part) je fais ça



    viewFille2Etapes1 = UIView(frame: CGRectMake(672, 108, 270, 480))

    Et ça marche nickel


     


    Pourquoi ça ne fonctionne pas pour un delegate dans un pageView



    var delegateEtape1: Etape1ViewControllerDelegate!

    et dans le viewDidLoad (ou autre part)



    delegateEtape1 = Etape1ViewControllerDelegate()

    xCode me met une erreur



     


    Etape1ViewControllerDelegate' cannot be constructed because it has no accessible initializers



     


    C'est débile, non ?


  • busterTheobusterTheo Membre
    mai 2015 modifié #6

    Et surtout que d'habitude, dans un simple controller, je n'ai pas de soucis pour le delegate en faisant comme ça



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

    Puis 



    var delegateEtape0: Etape0ViewControllerDelegate?

    Puis dans le viewDid........



    delegateEtape0?.configureNavbar?(self)

    Y'a un truc qui m'échappe


  • Bon, je suis convaincu que ta piste est la bonne.


    Et comme je sais, que souvent, le problème n'est pas unique, mais multiple, j'essaie de ne pas m'entêter, et donc j'ai essayé ça.



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

    Et

    var delegateEtape1: Etape1ViewControllerDelegate!

    Puis, parce que cela ne peut être que ici, à  mon avis (l'appel de la méthode)



    func populateControllersArray() {
    for i in 0...4 {
    let controller = storyboard!.instantiateViewControllerWithIdentifier("Etape1SbLevel\(i+1)") as ContentEtapesViewController
    controller.itemIndex = i
    delegateEtape1!.configureNavbar(controller)
    controllers.append(controller)

    }
    }

    avec ou non le "!"


     


    Pas d'erreur, mais ça plante et j'ai ce message habituel


     



     


    fatal error: unexpectedly found nil while unwrapping an Optional value



     


    ça sent grave les histoires de déclaration, de optionnal, de nil, de "?", de "!"


     


    Et si je fais



    var delegateEtape1: Etape1ViewControllerDelegate?

    Et ça



    func populateControllersArray() {
    for i in 0...4 {
    let controller = storyboard!.instantiateViewControllerWithIdentifier("Etape1SbLevel\(i+1)") as ContentEtapesViewController
    controller.itemIndex = i
    delegateEtape1?.configureNavbar(controller)
    controllers.append(controller)

    }
    }

    Donc, avec des "?", ça ne plante pas, mais cela ne fonctionne pas. La méthode n'est pas appelée.


  • CéroceCéroce Membre, Modérateur
    As-tu bien pensé à  dire quelle instance de Etape1ViewControllerDelegate est le délégué du PageViewController ?

    pageViewController.delegate = delegateEtape0
  • Oula.


    Merci Ceroce pour ta remarque certainement judicieuse, car je n'y ai pas pensé du tout. D'ailleurs, je vais mettre du temps à  la comprendre.


     


    à‰coute, je fais quelques essais avec ta remarque et je reviens.


    ça me semble une super idée. Merci.


  • busterTheobusterTheo Membre
    mai 2015 modifié #10

    Bon, je t'avoue que je n'y comprend plus rien.


     


    Je suis sur que c'est ta remarque qui pointe sur le problème.


     


    Mais je m'emmelle les pinceaux entre les delegate des controller et mes propres delegate.


     


    Par ex, (j'ai essayé avec et sans), je n'utilise pas UIPageViewControllerDelegate  et pageController.delegate = self


    car je ne vois pas la différence.


     


    D'autre part, j'ai essayé ton truc, un peu partout, et j'ai toujours cette erreur


     



     


    'ContentEtapesViewController' does not have a member named 'delegate'



     


    Je te met un fragment de code, que tu dois connaà®tre, car issue d'un tuto bien connu.


     


    Je laisse toutes les tentatives en commentaires, ainsi, tu vois mes essais, et surtout mes lacunes d;-)


     


    Désolé pour le code en vrac.



    var delegateEtape1: Etape1ViewControllerDelegate?

    Puis



    override func viewDidLoad() {
    super.viewDidLoad()
    // delegateEtape1 = Etape1ViewControllerDelegate()
    delegateEtape1?.configureNavbar(self)

    }

    // MARK: Configuration UIPageViewController

    func populateLevelsArray() {
    levels = ["Equilibre regard/sourire","Lignes horizontales","Les 3 étages","Angle naso-labial","Plan esthétique de ricketts"]
    }

    func populateControllersArray() {
    for i in 0...4 {
    let controller = storyboard!.instantiateViewControllerWithIdentifier("Etape1SbLevel\(i+1)") as ContentEtapesViewController
    controller.itemIndex = i
    controller.delegate = delegateEtape1
    // delegateEtape1? = Etape1ViewControllerDelegate()
    // delegateEtape1?.configureNavbar(controller)
    controllers.append(controller)

    }
    }

    func createPageViewController() {
    let pageController = UIPageViewController(transitionStyle: UIPageViewControllerTransitionStyle.Scroll, navigationOrientation: UIPageViewControllerNavigationOrientation.Horizontal, options: nil)
    pageController.dataSource = self
    // pageController.delegate = self
    // pageController.delegate = delegateEtape1


    // delegateEtape1?.configureNavbar?(pageController)


    if !controllers.isEmpty {
    pageController.setViewControllers([controllers[0]], direction: UIPageViewControllerNavigationDirection.Forward, animated: true, completion: nil)
    // delegateEtape1?.configureNavbar?([controllers[0]])

    }

    pageViewController = pageController
    // pageViewController.delegate = delegateEtape1
    addChildViewController(pageViewController!)
    self.view.addSubview(pageViewController!.view)
    pageViewController!.didMoveToParentViewController(self)
    // delegateEtape1?.configureNavbar?(pageViewController)

    }

    Merci d'avance pour tes futures réprimandes méritées  :'(


  • Et si je fais



    pageViewController.delegate = delegateEtape1

    j'ai cette erreur



     


    'Etape1ViewControllerDelegate' is not identical to 'UIPageViewControllerDelegate'



    booouuuuhhh, je vais pleurer  ::)


  • CéroceCéroce Membre, Modérateur
    mai 2015 modifié #12
    Dans la délégation, un objet (délégateur) délègue une partie de son fonctionnement à  un autre objet (délégué).
    Dans ton cas, une instance de UIPageViewController délègue son fonctionnement à  une instance de Etape1ViewController.

    1) Il faut dire au délégateur qui sera son délégué:
     
    pageViewController.delegate = etape1ViewController
    2) Le délégateur va appeler des méthodes sur son délégué. Il est donc nécessaire de formaliser ces méthodes. C'est le rôle du protocole UIPageViewControllerDelegate qui définit ces méthodes. La doc d'Apple explique dans quelles circonstances ces méthodes sont appelées par le délégateur.

    De ton côté tu dois dire que Etape1ViewController se conforme à  ce protocole; c'est à  dire qu'il promet qu'il va implémenter ces méthodes.
    class Etape1ViewController: UIViewController, UIPageViewControllerDelegate { 
    3) Tu implémentes les méthodes voulues dans Etape1ViewController et elles doivent être appelées.


    Franchement, j'ai donné pas mal de formations à  iOS, et ceux qui n'avaient jamais étudié le développement iOS trouvaient la délégation simple, alors que ceux qui s'y étaient essayé avant trouvaient ça compliqué!
    En fait, c'est réellement simple, il n'y a que deux objets. Fais un diagramme, tu verras.
  • busterTheobusterTheo Membre
    mai 2015 modifié #13

    Hummmm, merci Ceroce.


    ça me rassure énormément que tu sois formateur iOs, ainsi, tu es donc sur de ton coup, et je vais te suivre.


     


    Vu, que sur un simple controller, je n'ai aucun soucis avec les delegate, j'étais convaincu d'avoir tout compris, mais effectivement, dans le cas ou il existe déjà  un protocole associé, genre pour tableView ou pageView, et que je doive utiliser le mien, ça se complique.


     


    Mais tu dis plus haut



     


     


    pageViewController.delegate = delegateEtape0

    et là , tu dis



     


     


    pageViewController.delegate = etape1ViewController

    En gros, je dois dire que le delegate du pageView est mon delegate (delegateEtape1 plutôt que delegateEtape0) ou bienqu'il est le controller maà®tre (des sous-pages du pageView) : cad etape1ViewController ?


     


    Et, hormis cela, si je comprend bien l'histoire, je dois 



     


     


    dire que Etape1ViewController se conforme à  ce protocole

    avec



     


     


    class Etape1ViewController: UIViewController, UIPageViewControllerDelegate

    jusque là , pas de problème, mais ce que je ne comprend pas, c'est que je doive implémenter



     


     


    les méthodes voulues dans Etape1ViewController et elles doivent être appelées

    alors que je n'en ai pas besoin, et que j'ai simplement besoin de la mienne.


     


    ça me perturbe tout cela :


     


    Dire à  iOs : Je prend les méthodes de pageView, je dois les implémenter, mais ne les utilise pas, et utilise la mienne. Oulala, ça devient torturé comme truc, non ?


     


    D'autant plus que sur un simple controller, ça marche nickel, je ne comprend pas.


     


    Tu as certainement raison quand tu dis cela :


     



     


     


    Franchement, j'ai donné pas mal de formations à  iOS, et ceux qui n'avaient jamais étudié le développement iOS trouvaient la délégation simple, alors que ceux qui s'y étaient essayé avant trouvaient ça compliqué

    mais le soucis n'est pas tant d'implémenter ses propres delegate, mais de le faire quand il y en a déjà  qui existe (pageview).


     


    Bon, je vais creuser, mais tout ça me semble super complexe, alors que, comme tu dis, cela me semblait super simple.


  • J'ai pris une grande respiration, et je vais donc essayer de formaliser ce que tu m'as expliqué.


     


    Sur un simple controller, je crée mon délegate, et je lui dis de l'utiliser. ça fonctionne parfaitement.


     


    Sur un controller qui a déjà  des méthodes associées (joignables par son delegate), je dois lui dire :


    1- Je me met sur ton delegate


    2- J'implémente tes méthodes - Parce que y'a pas le choix quand on se met sur un delegate


    3- Je lui dis que son delegate, il se le met dans la poche, et il prend plutôt le mien.


     


    C'est carrément débile. On ne peut pas lui dire directement, qu'il prenne mon delegate (comme pour un simple controller), et donc, que ce ne soit pas nécessaire de demander de promettre ses méthodes à  l'aide de



     


     


    UIPageViewControllerDelegate

    Oups, je suis en train de devenir fou.


     


    Mais dis moi, si c'est bien comme cela que ça fonctionne, et alors, j'arrête de m'entêter et je poursuis selon tes conseils.


     


    Mais j'aime bien comprendre quand je sens une contradiction, même si c'est logique pour les pros.


     


    Encore merci pour tes efforts. Je sais que je suis dur de la feuille. N'empêche, tu m'as ouvert une énorme voie...


     


    Je ne voyais pas les choses comme ça. Je croyais que c'était beaucoup plus binaire, ce truc.


  • DrakenDraken Membre
    mai 2015 modifié #15

    Quand tu parle d'un délégué perso, c'est un objet de quel type ? Une classe déjà  existante avec des contraintes particulières, ou un objet entièrement à  toi ? Si c'est vraiment à  toi, tu peux te passer de toute la syntaxe des délégués, et faire ça simplement.


     


    Le système de MVC que je t'avais expliqué, c'étais aussi une sorte de délégué (dans l'esprit), mais codé plus simplement. 

  • busterTheobusterTheo Membre
    mai 2015 modifié #16

    Merci Draken, pour ta remarque.


     


    Ben non, regarde le début de mon post.


     


    C'est juste pour appeler une méthode à  la con qui est dans mon container général.


     


    Je ne peux l'appeler qu'à  partir d'un delegate comme expliqué plus haut.


  • Et j'y arrive sans problème à  partir d'un simple controller, mais pas à  partir d'un pageViewController


  • Jamais touché à  un pageViewController de ma vie !

  • AliGatorAliGator Membre, Modérateur

    Oula.
    Merci Ceroce pour ta remarque certainement judicieuse, car je n'y ai pas pensé du tout. D'ailleurs, je vais mettre du temps à  la comprendre.

    à‰coute, je fais quelques essais avec ta remarque et je reviens.
    ça me semble une super idée. Merci.

    Bah en fait c'est exactement ce que je te suggérais, mais mes explications supplémentaires t'ont certainement perdues. Ma réponse initiale c'était pour te dire "attention delegateEtape1 est un Optional, du coup il est peut-être nil, si tu ne l'as pas affecté à  une valeur. Et du coup s'il est nil, c'est normal que la méthode ne soit pas appelé, car il n'y a pas d'objet delegate sur laquelle l'appeler !"
  • ok AliGator, mais tu as vu, j'ai tout essayé...


  • CéroceCéroce Membre, Modérateur

    J'ai beaucoup de difficultés à  comprendre ce que tu cherches à  faire.


    Le fait qu'une classe se conforme à  un protocole ne l'empêche pas de se conformer à  d'autres protocoles. Un objet peut donc être le délégué de plusieurs objets de classes diverses.


     


    Je crois qu'à  ce stade, il faut que tu lâches ton clavier, et que tu dessines tes objets:


    - qui délégue à  qui ?


    - qui se conforme à  quel protocole ?


  • je suis allé voir pour la énième fois la page apple du délestage pageview, et il s'agit de méthodes en relation avec le passage d'une page à  l'autre (sous-pages, dirais-je), mais moi, c'est pas ça du tout, je veux juste appeler une méthode perso qui n'est pas dans mon controller (mais dans mon container général). Et cela, je peux le faire à  partir d'un simple controller, mais pas à  partir d'un pageview.


  • AliGatorAliGator Membre, Modérateur


    var delegateEtape1: Etape1ViewControllerDelegate!
    et dans le viewDidLoad (ou autre part)

    delegateEtape1 = Etape1ViewControllerDelegate()
    xCode me met une erreur
     
    C'est débile, non ?

    Bah non, c'est au contraire tout à  fait logique. Tu déclares ta variable delegateEtape1 comme étant un objet "d'un type quelconque, du moment qu'il se conforme au protocole Etape1ViewControllerDelegate". Mais "Etape1ViewControllerDelegate" n'est bien qu'un protocole, et non pas une classe concrète. Pour rappel, un protocol déclare juste les fonctions qu'un objet est sensé implémenter, mais ne propose pas d'implémentation.

    Donc tu ne peux pas "instancier un protocole", au sens "créer un objet directement de ce type" avec "Etape1ViewControllerDelegate()". Il faut créer une instance d'une classe concrète se conformant à  ce protocole


    C'est un peu comme si tu avais un protocole appelé "UnTrucQuiSaitRouler", protocole définissant la signature pour une méthode "func rouler()". Ce n'est qu'un protocole, tu ne peux pas directement créer un objet "UnTrucQuiSaitRouler()" car tu ne dis pas ce que c'est que ce truc, ce n'est qu'un protocole qui décrit une interface, (mais pas d'implémentation). Par contre tu peux ensuite avoir des classes "Velo" et "Voiture", qui toutes 2 se conforment au protocole UnTrucQuiSaitRouler, et qui donc vont avoir une implémentation de la méthode "func rouler()". Et là  tu pourras faire "Velo()" ou "Voiture()" pour créer un nouveau vélo ou une nouvelle voiture, qui se trouve être UnTrucQuiSaitRouler particulier.
    Bah là  c'est pareil, tu peux pas instancier "Etape1ViewControllerDelegate()" car "Etape1ViewControllerDelegate" est un protocole. Il faut que tu instancies une classe réelle, concrète (ou que tu fournisses un objet déjà  existant, comme self ou comme le ViewController parent, etc).
     

    Et surtout que d'habitude, dans un simple controller, je n'ai pas de soucis pour le delegate en faisant comme ça


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

    var delegateEtape0: Etape0ViewControllerDelegate?
    Puis dans le viewDid........

    delegateEtape0?.configureNavbar?(self)
    Y'a un truc qui m'échappe

    Le problème qu'on essaye de t'expliquer, c'est que dans ton exemple avec Etape1, delegateEtape1 est nil, car tu as oublié de lui affecter une valeur, tu as oublié de l'affecter à  un objet (une instance) qui effectivement sera le délégué qui va recevoir le le message configureNavbar. Il faut à  un moment faire un "delegateEtape1 = unObjetSeConformantAuProtocole" pour lui dire QUI est ce delegateEtape1 à  qui tu souhaites que le message configureNavbar soit envoyé, car pour l'instant tu ne lui as rien dit et il n'y a personne d'indiqué (nil) pour répondre au message.

    Si ça marche pour Etape0 c'est sans doute parce qu'il y a du code (que tu ne nous montre pas) qui a affecté une valeur à  ta propriété "delegateEtape0", ce qui fait qu'elle n'est pas nil comme c'est le cas pour delegateEtape1. Ou alors pour Etape0 tu l'as peut-être pas fait par code, mais peut-être que ce delegateEtape0 c'est un IBOutlet et que tu l'as connecté à  un objet existant via Interface Builder, mais en tout cas lui il a une valeur, alors que la propriété delegateEtape1 n'a toujours aucune valeur (nil) car tu ne l'as affectée nulle part à  un objet existant.
  • bon, je vais vous envoyer tout mon code, pare que là , je suis out.


     


    Je ne sais plus comment expliquer l'histoire.


     


    Merci pour vos effort, et en tout cas, je relis quotidiennement vos réponses, et cela me pousse à  m'instruire d'avantage.


     


    Code au prochain post.


     


    Code propre et épuré des tentatives.


     


    D'ailleurs je vais mettre tout le projet.


  • CéroceCéroce Membre, Modérateur
    mai 2015 modifié #25

    Dans un UIPageViewController, une page est représentée par une sous-classe de UIViewController. (Appelons-là  Page1ViewController). Si quelque chose change sur cette page, c'est elle qui doit prévenir le contrôleur principal (MainViewController), pas le UIPageViewController.


     


    Donc:


    1) Définis un protocole Page1ViewControllerDelegate. 


     


    2) MainViewController doit se conformer à  Page1ViewControllerDelegate et implémenter les méthodes que ce protocole définit.


     


    3) Page1ViewController doit posséder une propriété 'delegate' de type Page1ViewControllerDelegate?. ça veut dire que Page1ViewController ne sait pas quel est le type exact du délégué, seulement qu'il se conforme au protocole.


     


    4) MainViewController doit fixer cette propriété en passant 'self'. (puisque le délégué, c'est lui).


     


    Désolé de ne pas fournir de code, mais je ne maà®trise pas encore assez Swift pour cela.


  • AliGatorAliGator Membre, Modérateur
    En fait je crois que Theo ton problème c'est pas un problème de code, ni aux PageViewController en particulier, mais de compréhension du pattern "delegate" en général, et des principes de ce qu'est un protocole et comment tout cela s'imbrique.

    La logique n'est pas compliquée en soit, mais il faut l'avoir fait au moins une fois pour comprendre, et surtout il faut s'assoir et lire sur le sujet à  tête reposée plutôt que la tête plongée dans le code.
  • Ok Céroce, pas de pb pour pas de code swift.


     


    Je comptais vous envoyer mon projet, mais le pb est que il faudrait expliquer trop de chose pour la navigation provisoire et celle avec les swipe, etc...


     


    Je vais donc poster du code, mais avant je ré-explique le bouzin.


     


     


    En gros, il s'agit d'un projet ou on passe d'étape en étape.


     


     


    Le tout est dans un container avec slideNav sur le côté - Vous connaissez les autos en questions. Container et fonction toggle, etc


     


     


    La première étape (etape0) est associée à  un simple controller avec inscription (champs et photos).


     


    Dans cette étape, la barre de nav s'affiche bien (ok pour le delegate)



    import UIKit
    import CoreData

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

    class Etape0ViewController: UIViewController, UITextViewDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

    // MARK: Properties

    @IBOutlet weak var nomTextField: UITextField!
    @IBOutlet weak var prenomTextField: UITextField!
    @IBOutlet weak var dateCreationTextField: UITextField!
    @IBOutlet weak var sexeTextField: UITextField!
    @IBOutlet weak var ageTextField: UITextField!
    @IBOutlet weak var teintTextField: UITextField!
    @IBOutlet weak var yeuxTextField: UITextField!
    @IBOutlet weak var changerTextField: UITextField!
    @IBOutlet weak var personnaliteTextField: UITextField!
    @IBOutlet weak var physiqueTextField: UITextField!
    @IBOutlet weak var typeTextField: UITextField!

    @IBOutlet weak var viewMereEtape0: UIView!

    // MARK: - Variables

    var viewOmbreVignetteFrontalPatient: UIView!
    var viewVignetteFrontalPatient: UIView!
    var viewMaskFrontalPatient: UIView!
    var frontalPatientImageView: UIImageView!

    var viewOmbreVignetteBpnmbfPatient: UIView!
    var viewVignetteBpnmbfPatient: UIView!
    var viewMaskBpnmbfPatient: UIView!
    var BpnmbfPatientImageView: UIImageView!

    var viewOmbreVignetteCfnmsPatient: UIView!
    var viewVignetteCfnmsPatient: UIView!
    var viewMaskCfnmsPatient: UIView!
    var CfnmsPatientImageView: UIImageView!

    var viewOmbreVignetteDpnmsPatient: UIView!
    var viewVignetteDpnmsPatient: UIView!
    var viewMaskDpnmsPatient: UIView!
    var DpnmsPatientImageView: UIImageView!

    var viewOmbreVignetteEaiETsPatient: UIView!
    var viewVignetteEaiETsPatient: UIView!
    var viewMaskEaiETsPatient: UIView!
    var EaiETsPatientImageView: UIImageView!

    var delegateEtape0: Etape0ViewControllerDelegate?

    var patientsViewController: PatientsViewController!
    var frontalPatientFullURL: String?
    var BpnmbfPatientFullURL: String?
    var CfnmsPatientFullURL: String?
    var DpnmsPatientFullURL: String?
    var EaiETsPatientFullURL: String?

    var imageViewIntro: UIImageView!

    // Pour Update
    var existingItem: NSManagedObject!

    // Pour recup du UIImageView dans le UIImagePickerController
    var lastTappedImageView: UIImageView?

    // MARK: Actions

    @IBAction func goEtape1Action(sender: AnyObject) {
    enregistrer()
    delegateEtape0?.goEtape1?()
    }

    // MARK: View Life Cycle

    override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    if (viewPopSlider != nil) {
    viewPopSlider?.removeFromSuperview()
    }

    if (introAppli == true) {
    UIView.animateWithDuration(3.0, delay: 2.0, options: nil, animations: {
    self.imageViewIntro.alpha = 0.0
    }, completion: {
    (finished: Bool) -> Void in
    self.imageViewIntro.removeFromSuperview()
    myFunctions.confSlider(self)
    }
    )
    } else {
    myFunctions.confSlider(self)
    }
    }

    override func viewDidLoad() {
    super.viewDidLoad()

    boxViewMere()

    boxVignettes()

    if (introAppli == true) {
    imageViewIntro = UIImageView(frame: CGRectMake(0, 0, 1024, 768))

    self.imageViewIntro.image = UIImage(named: "intro.jpg")
    self.imageViewIntro.alpha = 1.0
    self.view.addSubview(imageViewIntro)
    }

    taperPhoto()

    if frontalPatientFullURL == nil {
    self.frontalPatientImageView.image = UIImage(named: noPhotoPNG)
    }
    if BpnmbfPatientFullURL == nil {
    self.BpnmbfPatientImageView.image = UIImage(named: noPhotoPNG)
    }
    if CfnmsPatientFullURL == nil {
    self.CfnmsPatientImageView.image = UIImage(named: noPhotoPNG)
    }
    if DpnmsPatientFullURL == nil {
    self.DpnmsPatientImageView.image = UIImage(named: noPhotoPNG)
    }
    if EaiETsPatientFullURL == nil {
    self.EaiETsPatientImageView.image = UIImage(named: noPhotoPNG)
    }

    delegateEtape0?.configureNavbar?(self)

    }

    // Build Fond viewMereEtapes

    func boxViewMere() {
    viewMereEtape0.layer.cornerRadius = 5.0
    viewMereEtape0.layer.shadowColor = UIColor.blackColor().CGColor
    viewMereEtape0.layer.shadowOffset = CGSize(width: 1, height: 1)
    viewMereEtape0.layer.shadowOpacity = 0.5
    viewMereEtape0.layer.shadowRadius = 5
    }

    // Build Vignettes
    func boxVignettes() {

    // 0- Ombre
    viewOmbreVignetteFrontalPatient = UIView(frame: CGRectMake(32, 425, 170, 205))
    viewOmbreVignetteFrontalPatient.backgroundColor = fondsColor
    viewOmbreVignetteFrontalPatient.layer.cornerRadius = 5.0
    viewOmbreVignetteFrontalPatient.layer.shadowColor = UIColor.blackColor().CGColor
    viewOmbreVignetteFrontalPatient.layer.shadowOffset = CGSize(width: 1, height: 1)
    viewOmbreVignetteFrontalPatient.layer.shadowOpacity = 0.5
    viewOmbreVignetteFrontalPatient.layer.shadowRadius = 5
    self.view.addSubview(viewOmbreVignetteFrontalPatient)
    // 1- Box
    viewVignetteFrontalPatient = UIView(frame: CGRectMake(32, 425, 170, 205))
    viewVignetteFrontalPatient.backgroundColor = fondsColor
    viewVignetteFrontalPatient.layer.cornerRadius = 5.0
    self.view.addSubview(viewVignetteFrontalPatient)
    // 2- Photo
    frontalPatientImageView = UIImageView(frame: CGRectMake(0, 0, 170, 135))
    viewVignetteFrontalPatient.addSubview(frontalPatientImageView)
    // 3- Masque
    viewMaskFrontalPatient = UIView(frame: CGRectMake(0, 0, 170, 205))
    viewMaskFrontalPatient.backgroundColor = fondsColor
    viewMaskFrontalPatient.layer.cornerRadius = 5.0
    viewVignetteFrontalPatient.addSubview(viewMaskFrontalPatient)
    // Masking
    viewVignetteFrontalPatient.maskView = viewMaskFrontalPatient

    // 0- Ombre
    viewOmbreVignetteBpnmbfPatient = UIView(frame: CGRectMake(229, 425, 170, 205))
    viewOmbreVignetteBpnmbfPatient.backgroundColor = fondsColor
    viewOmbreVignetteBpnmbfPatient.layer.cornerRadius = 5.0
    viewOmbreVignetteBpnmbfPatient.layer.shadowColor = UIColor.blackColor().CGColor
    viewOmbreVignetteBpnmbfPatient.layer.shadowOffset = CGSize(width: 1, height: 1)
    viewOmbreVignetteBpnmbfPatient.layer.shadowOpacity = 0.5
    viewOmbreVignetteBpnmbfPatient.layer.shadowRadius = 5
    self.view.addSubview(viewOmbreVignetteBpnmbfPatient)
    // 1- Box
    viewVignetteBpnmbfPatient = UIView(frame: CGRectMake(229, 425, 170, 205))
    viewVignetteBpnmbfPatient.backgroundColor = fondsColor
    viewVignetteBpnmbfPatient.layer.cornerRadius = 5.0
    self.view.addSubview(viewVignetteBpnmbfPatient)
    // 2- Photo
    BpnmbfPatientImageView = UIImageView(frame: CGRectMake(0, 0, 170, 135))
    viewVignetteBpnmbfPatient.addSubview(BpnmbfPatientImageView)
    // 3- Masque
    viewMaskBpnmbfPatient = UIView(frame: CGRectMake(0, 0, 170, 205))
    viewMaskBpnmbfPatient.backgroundColor = fondsColor
    viewMaskBpnmbfPatient.layer.cornerRadius = 5.0
    viewVignetteBpnmbfPatient.addSubview(viewMaskBpnmbfPatient)
    // Masking
    viewVignetteBpnmbfPatient.maskView = viewMaskBpnmbfPatient

    // 0- Ombre
    viewOmbreVignetteCfnmsPatient = UIView(frame: CGRectMake(427, 425, 170, 205))
    viewOmbreVignetteCfnmsPatient.backgroundColor = fondsColor
    viewOmbreVignetteCfnmsPatient.layer.cornerRadius = 5.0
    viewOmbreVignetteCfnmsPatient.layer.shadowColor = UIColor.blackColor().CGColor
    viewOmbreVignetteCfnmsPatient.layer.shadowOffset = CGSize(width: 1, height: 1)
    viewOmbreVignetteCfnmsPatient.layer.shadowOpacity = 0.5
    viewOmbreVignetteCfnmsPatient.layer.shadowRadius = 5
    self.view.addSubview(viewOmbreVignetteCfnmsPatient)
    // 1- Box
    viewVignetteCfnmsPatient = UIView(frame: CGRectMake(427, 425, 170, 205))
    viewVignetteCfnmsPatient.backgroundColor = fondsColor
    viewVignetteCfnmsPatient.layer.cornerRadius = 5.0
    self.view.addSubview(viewVignetteCfnmsPatient)
    // 2- Photo
    CfnmsPatientImageView = UIImageView(frame: CGRectMake(0, 0, 170, 135))
    viewVignetteCfnmsPatient.addSubview(CfnmsPatientImageView)
    // 3- Masque
    viewMaskCfnmsPatient = UIView(frame: CGRectMake(0, 0, 170, 205))
    viewMaskCfnmsPatient.backgroundColor = fondsColor
    viewMaskCfnmsPatient.layer.cornerRadius = 5.0
    viewVignetteCfnmsPatient.addSubview(viewMaskCfnmsPatient)
    // Masking
    viewVignetteCfnmsPatient.maskView = viewMaskCfnmsPatient

    // 0- Ombre
    viewOmbreVignetteDpnmsPatient = UIView(frame: CGRectMake(626, 425, 170, 205))
    viewOmbreVignetteDpnmsPatient.backgroundColor = fondsColor
    viewOmbreVignetteDpnmsPatient.layer.cornerRadius = 5.0
    viewOmbreVignetteDpnmsPatient.layer.shadowColor = UIColor.blackColor().CGColor
    viewOmbreVignetteDpnmsPatient.layer.shadowOffset = CGSize(width: 1, height: 1)
    viewOmbreVignetteDpnmsPatient.layer.shadowOpacity = 0.5
    viewOmbreVignetteDpnmsPatient.layer.shadowRadius = 5
    self.view.addSubview(viewOmbreVignetteDpnmsPatient)
    // 1- Box
    viewVignetteDpnmsPatient = UIView(frame: CGRectMake(626, 425, 170, 205))
    viewVignetteDpnmsPatient.backgroundColor = fondsColor
    viewVignetteDpnmsPatient.layer.cornerRadius = 5.0
    self.view.addSubview(viewVignetteDpnmsPatient)
    // 2- Photo
    DpnmsPatientImageView = UIImageView(frame: CGRectMake(0, 0, 170, 135))
    viewVignetteDpnmsPatient.addSubview(DpnmsPatientImageView)
    // 3- Masque
    viewMaskDpnmsPatient = UIView(frame: CGRectMake(0, 0, 170, 205))
    viewMaskDpnmsPatient.backgroundColor = fondsColor
    viewMaskDpnmsPatient.layer.cornerRadius = 5.0
    viewVignetteDpnmsPatient.addSubview(viewMaskDpnmsPatient)
    // Masking
    viewVignetteDpnmsPatient.maskView = viewMaskDpnmsPatient

    // 0- Ombre
    viewOmbreVignetteEaiETsPatient = UIView(frame: CGRectMake(822, 425, 170, 205))
    viewOmbreVignetteEaiETsPatient.backgroundColor = fondsColor
    viewOmbreVignetteEaiETsPatient.layer.cornerRadius = 5.0
    viewOmbreVignetteEaiETsPatient.layer.shadowColor = UIColor.blackColor().CGColor
    viewOmbreVignetteEaiETsPatient.layer.shadowOffset = CGSize(width: 1, height: 1)
    viewOmbreVignetteEaiETsPatient.layer.shadowOpacity = 0.5
    viewOmbreVignetteEaiETsPatient.layer.shadowRadius = 5
    self.view.addSubview(viewOmbreVignetteEaiETsPatient)
    // 1- Box
    viewVignetteEaiETsPatient = UIView(frame: CGRectMake(822, 425, 170, 205))
    viewVignetteEaiETsPatient.backgroundColor = fondsColor
    viewVignetteEaiETsPatient.layer.cornerRadius = 5.0
    self.view.addSubview(viewVignetteEaiETsPatient)
    // 2- Photo
    EaiETsPatientImageView = UIImageView(frame: CGRectMake(0, 0, 170, 135))
    viewVignetteEaiETsPatient.addSubview(EaiETsPatientImageView)
    // 3- Masque
    viewMaskEaiETsPatient = UIView(frame: CGRectMake(0, 0, 170, 205))
    viewMaskEaiETsPatient.backgroundColor = fondsColor
    viewMaskEaiETsPatient.layer.cornerRadius = 5.0
    viewVignetteEaiETsPatient.addSubview(viewMaskEaiETsPatient)
    // Masking
    viewVignetteEaiETsPatient.maskView = viewMaskEaiETsPatient
    }

    func enregistrer() {
    if(self.frontalPatientFullURL == nil) {
    frontalPatientFullURL = ""
    }

    if(self.BpnmbfPatientFullURL == nil) {
    BpnmbfPatientFullURL = ""
    }

    if(self.CfnmsPatientFullURL == nil) {
    CfnmsPatientFullURL = ""
    }

    if(self.DpnmsPatientFullURL == nil) {
    DpnmsPatientFullURL = ""
    }

    if(self.EaiETsPatientFullURL == nil) {
    EaiETsPatientFullURL = ""
    }

    var appDel:AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
    var context: NSManagedObjectContext = appDel.managedObjectContext!
    let entity = NSEntityDescription.entityForName("Patients", inManagedObjectContext: context)

    if listeDesVariables.edition == true {
    existingItem.setValue(nomTextField.text, forKey: "nom")
    existingItem.setValue(prenomTextField.text, forKey: "prenom")
    existingItem.setValue(dateCreationTextField.text, forKey: "dateCreation")
    existingItem.setValue(sexeTextField.text, forKey: "sexe")
    existingItem.setValue(ageTextField.text, forKey: "age")
    existingItem.setValue(teintTextField.text, forKey: "teint")
    existingItem.setValue(yeuxTextField.text, forKey: "yeux")
    existingItem.setValue(changerTextField.text, forKey: "changer")
    existingItem.setValue(personnaliteTextField.text, forKey: "personnalite")
    existingItem.setValue(physiqueTextField.text, forKey: "physique")
    existingItem.setValue(typeTextField.text, forKey: "type")
    existingItem.setValue(listeDesVariables.frontalPatientFullURL, forKey: "photoFrontal")
    existingItem.setValue(listeDesVariables.BpnmbfPatientFullURL, forKey: "photo2")
    existingItem.setValue(listeDesVariables.CfnmsPatientFullURL, forKey: "photo3")
    existingItem.setValue(listeDesVariables.DpnmsPatientFullURL, forKey: "photo4")
    existingItem.setValue(listeDesVariables.EaiETsPatientFullURL, forKey: "photo5")
    } else {
    var newUser = Patients(entity: entity!, insertIntoManagedObjectContext: context)
    newUser.nom = nomTextField.text
    newUser.prenom = prenomTextField.text
    newUser.dateCreation = dateCreationTextField.text
    newUser.sexe = sexeTextField.text
    newUser.age = ageTextField.text
    newUser.teint = teintTextField.text
    newUser.yeux = yeuxTextField.text
    newUser.changer = changerTextField.text
    newUser.personnalite = personnaliteTextField.text
    newUser.physique = physiqueTextField.text
    newUser.type = typeTextField.text
    newUser.photoFrontal = frontalPatientFullURL!
    newUser.photo2 = BpnmbfPatientFullURL!
    newUser.photo3 = CfnmsPatientFullURL!
    newUser.photo4 = DpnmsPatientFullURL!
    newUser.photo5 = EaiETsPatientFullURL!

    listeDesVariables.nomString = nomTextField.text
    listeDesVariables.prenomString = prenomTextField.text
    listeDesVariables.dateCreationString = dateCreationTextField.text
    listeDesVariables.sexeString = sexeTextField.text
    listeDesVariables.ageString = ageTextField.text
    listeDesVariables.teintString = teintTextField.text
    listeDesVariables.yeuxString = yeuxTextField.text
    listeDesVariables.changerString = changerTextField.text
    listeDesVariables.personnaliteString = personnaliteTextField.text
    listeDesVariables.physiqueString = physiqueTextField.text
    listeDesVariables.typeString = typeTextField.text
    listeDesVariables.frontalPatientFullURL = frontalPatientFullURL!
    listeDesVariables.BpnmbfPatientFullURL = BpnmbfPatientFullURL!
    listeDesVariables.CfnmsPatientFullURL = CfnmsPatientFullURL!
    listeDesVariables.DpnmsPatientFullURL = DpnmsPatientFullURL!
    listeDesVariables.EaiETsPatientFullURL = EaiETsPatientFullURL!
    }
    context.save(nil)
    }

    // MARK: Image functions

    func taperPhoto() {
    let taperPhoto: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "choisirImage:")
    taperPhoto.numberOfTapsRequired = 1
    let taperPhoto2: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "choisirImage:")
    taperPhoto2.numberOfTapsRequired = 1
    let taperPhoto3: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "choisirImage:")
    taperPhoto3.numberOfTapsRequired = 1
    let taperPhoto4: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "choisirImage:")
    taperPhoto4.numberOfTapsRequired = 1
    let taperPhoto5: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "choisirImage:")
    taperPhoto5.numberOfTapsRequired = 1

    frontalPatientImageView.addGestureRecognizer(taperPhoto)
    frontalPatientImageView.userInteractionEnabled = true

    BpnmbfPatientImageView.addGestureRecognizer(taperPhoto2)
    BpnmbfPatientImageView.userInteractionEnabled = true

    CfnmsPatientImageView.addGestureRecognizer(taperPhoto3)
    CfnmsPatientImageView.userInteractionEnabled = true

    DpnmsPatientImageView.addGestureRecognizer(taperPhoto4)
    DpnmsPatientImageView.userInteractionEnabled = true

    EaiETsPatientImageView.addGestureRecognizer(taperPhoto5)
    EaiETsPatientImageView.userInteractionEnabled = true
    }

    func choisirImage(recognizer: UITapGestureRecognizer) {
    if recognizer.state == .Ended {
    self.lastTappedImageView = recognizer.view as? UIImageView
    if let imageView = self.lastTappedImageView {
    // if let imageView = recognizer.view as? UIImageView {
    let picker = MyImagePickerController()
    picker.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
    picker.mediaTypes = UIImagePickerController.availableMediaTypesForSourceType(picker.sourceType)!
    picker.delegate = self
    picker.allowsEditing = false

    let popover = UIPopoverController(contentViewController: picker)
    popover.dismissPopoverAnimated(true)
    popover.presentPopoverFromRect(imageView.frame, inView: imageView.superview!, permittedArrowDirections : UIPopoverArrowDirection.Any, animated: true)
    // self.view.presentViewController(picker, animated: true, completion: nil)

    }
    }
    }
    func scaledImageWithImage(image: UIImage, size: CGSize) -> UIImage {
    let scale: CGFloat = max(size.width/image.size.width, size.height/image.size.height)
    let width: CGFloat = image.size.width * scale
    let height: CGFloat = image.size.height * scale
    let imageRect: CGRect = CGRectMake((size.width-width)/2.0, (size.height-height)/2.0, width, height)

    UIGraphicsBeginImageContextWithOptions(size, false, 0)
    image.drawInRect(imageRect)
    let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return newImage
    }

    // MARK: UITextView PlaceHolder functions

    func masquePlaceholder(aTextview: UITextView) {
    aTextview.textColor = UIColor.darkTextColor()
    }

    func curseurDebut(aTextView: UITextView) {
    aTextView.text = ""
    dispatch_async(dispatch_get_main_queue(), {
    aTextView.selectedRange = NSMakeRange(0, 0);
    })
    }
    // MARK: UITextViewDelegate

    override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
    // Le clavier descend si le curseur est dans tous les champs et que l'on clique sur le fond
    self.view.endEditing(true)
    }

    // MARK: - UIImagePickerControllerDelegate Methods

    func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {
    let imagePickee: UIImage = info[UIImagePickerControllerOriginalImage] as UIImage

    //Scale photo
    let screenSize: CGSize = UIScreen.mainScreen().bounds.size
    var newImageScaled: UIImage = scaledImageWithImage(imagePickee, size: CGSize(width: screenSize.width, height: screenSize.height))

    //L'image sélectionnée va dans le UIImageView
    self.lastTappedImageView?.image = newImageScaled

    //Adresse répertoire photos
    let paths: NSArray = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
    let documentsDir: NSString = paths.objectAtIndex(0) as NSString

    //On fabrique le nom de la photo
    var dateFormat = NSDateFormatter()
    dateFormat.dateFormat = "yyyy-MM-dd-HH-mm-ss"
    let now: NSDate = NSDate(timeIntervalSinceNow: 0)
    let theDate: NSString = dateFormat.stringFromDate(now)

    if lastTappedImageView == frontalPatientImageView {
    // On fabrique le nom de la photo
    frontalPatientFullURL = NSString(format: "Frontal\(nomTextField.text)-%@.png", theDate)
    listeDesVariables.frontalPatientFullURL = NSString(format: "Frontal\(nomTextField.text)-%@.png", theDate)

    // On fabrique le chemin total
    let pathFull: NSString = documentsDir.stringByAppendingString(frontalPatientFullURL!)

    // On fabrique l'image
    let pngFullData: NSData = UIImagePNGRepresentation(newImageScaled)
    pngFullData.writeToFile(pathFull, atomically: true)
    }

    if lastTappedImageView == BpnmbfPatientImageView {
    // On fabrique le nom de la photo
    BpnmbfPatientFullURL = NSString(format: "Bpnmbf\(nomTextField.text)-%@.png", theDate)
    listeDesVariables.BpnmbfPatientFullURL = NSString(format: "Bpnmbf\(nomTextField.text)-%@.png", theDate)

    // On fabrique le chemin total
    let pathFull: NSString = documentsDir.stringByAppendingString(BpnmbfPatientFullURL!)

    // On fabrique l'image
    let pngFullData: NSData = UIImagePNGRepresentation(newImageScaled)
    pngFullData.writeToFile(pathFull, atomically: true)
    }

    if lastTappedImageView == CfnmsPatientImageView {
    // On fabrique le nom de la photo
    CfnmsPatientFullURL = NSString(format: "Cfnms\(nomTextField.text)-%@.png", theDate)
    listeDesVariables.CfnmsPatientFullURL = NSString(format: "Cfnms\(nomTextField.text)-%@.png", theDate)

    // On fabrique le chemin total
    let pathFull: NSString = documentsDir.stringByAppendingString(CfnmsPatientFullURL!)

    // On fabrique l'image
    let pngFullData: NSData = UIImagePNGRepresentation(newImageScaled)
    pngFullData.writeToFile(pathFull, atomically: true)
    }

    if lastTappedImageView == DpnmsPatientImageView {
    // On fabrique le nom de la photo
    DpnmsPatientFullURL = NSString(format: "Dpnms\(nomTextField.text)-%@.png", theDate)
    listeDesVariables.DpnmsPatientFullURL = NSString(format: "Dpnms\(nomTextField.text)-%@.png", theDate)

    // On fabrique le chemin total
    let pathFull: NSString = documentsDir.stringByAppendingString(DpnmsPatientFullURL!)

    // On fabrique l'image
    let pngFullData: NSData = UIImagePNGRepresentation(newImageScaled)
    pngFullData.writeToFile(pathFull, atomically: true)
    }

    if lastTappedImageView == EaiETsPatientImageView {
    // On fabrique le nom de la photo
    EaiETsPatientFullURL = NSString(format: "EaiETs\(nomTextField.text)-%@.png", theDate)
    listeDesVariables.EaiETsPatientFullURL = NSString(format: "EaiETs\(nomTextField.text)-%@.png", theDate)

    // On fabrique le chemin total
    let pathFull: NSString = documentsDir.stringByAppendingString(EaiETsPatientFullURL!)

    // On fabrique l'image
    let pngFullData: NSData = UIImagePNGRepresentation(newImageScaled)
    pngFullData.writeToFile(pathFull, atomically: true)
    }

    self.lastTappedImageView = nil

    picker.dismissViewControllerAnimated(true, completion: nil)
    }
    }







    Ensuite on passe à  l'étape suivante puis etc.


     


    Le truc complexe est que toutes les étapes, sauf l'étape 0, sont des pageView, car elles ont des sous-étapes. En gros, on doit valider plusieurs écran par étapes, sauf pour l'étape 0.


     


    On navigue au sein de chacune des étapes (sauf étape0) par le swipe naturel du pageview de chaque étape, puis on passe à  l'étape suivante avec un UIPanGestureRecognizer perso


     


     


    Donc, en gros, à  partir de l'étape 0, je parviens à  lancer la fonction 



    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)

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

    println("configureNavbar - \(etapeViewController)")
    }

    qui se trouve dans mon container général à  l'aide de



    delegateEtape0?.configureNavbar?(self)

    lors du viewDidLoad


     


    Mais dans le cas des etape1, ou les suivantes, cela ne fonctionne pas.


     


    Je met ici le code complet de etape1ViewController qui est le controller maitre pour ses sous-pages qui sont Etape1L1, Etape1L2, etc.


     


    Ainsi, ce sera plus clair, j'espère.



    import UIKit
    import CoreData

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

    class Etape1ViewController: UIViewController, UIPageViewControllerDataSource, /*UIPageViewControllerDelegate,*/ UINavigationControllerDelegate {

    // MARK: Properties

    @IBOutlet weak var viewMereEtapes1: UIView!

    // MARK: - Variables

    var pageViewController: UIPageViewController!
    var contentEtapesViewController: ContentEtapesViewController?

    var delegateEtape1: Etape1ViewControllerDelegate?

    var controllers = [ContentEtapesViewController]()

    var pageControl: UIPageControl!
    var levelLabel: UILabel!
    var levels = [String]()

    // MARK: View Life Cycle

    override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    viewMereEtapes1.layer.cornerRadius = 5.0
    viewMereEtapes1.layer.shadowColor = UIColor.blackColor().CGColor
    viewMereEtapes1.layer.shadowOffset = CGSize(width: 1, height: 1)
    viewMereEtapes1.layer.shadowOpacity = 0.5
    viewMereEtapes1.layer.shadowRadius = 5

    populateLevelsArray()
    populateControllersArray()
    createPageViewController()
    setupPageControl()
    }

    override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

    }

    override func viewDidLoad() {
    super.viewDidLoad()
    delegateEtape1?.configureNavbar?(self)

    }

    // MARK: Configuration UIPageViewController

    func populateLevelsArray() {
    levels = ["Equilibre regard/sourire","Lignes horizontales","Les 3 étages","Angle naso-labial","Plan esthétique de ricketts"]
    }

    func populateControllersArray() {
    for i in 0...4 {
    let controller = storyboard!.instantiateViewControllerWithIdentifier("Etape1SbLevel\(i+1)") as ContentEtapesViewController
    controller.itemIndex = i
    controllers.append(controller)
    }
    }

    func createPageViewController() {
    let pageController = UIPageViewController(transitionStyle: UIPageViewControllerTransitionStyle.Scroll, navigationOrientation: UIPageViewControllerNavigationOrientation.Horizontal, options: nil)
    pageController.dataSource = self

    if !controllers.isEmpty {
    pageController.setViewControllers([controllers[0]], direction: UIPageViewControllerNavigationDirection.Forward, animated: true, completion: nil)
    }

    pageViewController = pageController
    addChildViewController(pageViewController!)
    self.view.addSubview(pageViewController!.view)
    pageViewController!.didMoveToParentViewController(self)
    }

    // MARK: Configuration UIPageControl

    func setupPageControl() {
    if pageControl == nil {
    pageControl = UIPageControl(frame: CGRectMake(475,30,86,55))
    pageControl.addTarget(self, action: "clickControl", forControlEvents: UIControlEvents.TouchUpInside)
    self.view.addSubview(pageControl)

    pageControl.currentPage = 0
    pageControl.numberOfPages = controllers.count

    pageControl.pageIndicatorTintColor = UIColor.lightGrayColor()
    pageControl.currentPageIndicatorTintColor = UIColor.darkGrayColor()
    pageControl.backgroundColor = UIColor.clearColor()
    pageControl.contentHorizontalAlignment = .Center

    levelLabel = UILabel(frame: CGRectMake(570, 40, 350, 30))
    levelLabel.text = levels[0]
    levelLabel.textColor = UIColor.darkGrayColor()
    levelLabel.font = UIFont(name: "Arial", size: 16.0)
    levelLabel.backgroundColor = UIColor.clearColor()
    levelLabel.textAlignment = .Left
    self.view.addSubview(levelLabel)
    } else {
    pageControl.currentPage = 0
    levelLabel.text = levels[0]
    }
    }

    func clickControl() {
    println(pageControl.currentPage)
    }

    // MARK: - UIPageViewControllerDataSource

    func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
    if let controller = viewController as? ContentEtapesViewController {
    if controller.itemIndex > 0 {
    pageControl.currentPage = controller.itemIndex
    levelLabel.text = levels[pageControl.currentPage]
    return controllers[controller.itemIndex - 1]
    } else {
    pageControl.currentPage = 0
    levelLabel.text = levels[0]
    }
    }
    return nil
    }

    func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
    if let controller = viewController as? ContentEtapesViewController {
    if controller.itemIndex < controllers.count - 1 {
    // listeDesVariables.imprileLdV()
    pageControl.currentPage = controller.itemIndex
    levelLabel.text = levels[pageControl.currentPage]
    return controllers[controller.itemIndex + 1]
    } else {
    pageControl.currentPage = controllers.count
    levelLabel.text = levels[pageControl.numberOfPages-1]
    }
    }
    return nil
    }

    }

    Merci d'avance

  • Ok AliGator pour ta remarque, je suis entièrement d'accord avec toi.


     


    Mais tout ce que j'ai lu sur le sujet ne m'aide pas, car on y parle des delegate des tableView et autres (que je comprend parfaitement, car je les utilise), et lorsque l'on parle de ses propres delegate perso, on n'en parle jamais lorsque l'on veut les utiliser sur des trucs qui ont déjà  leur delegate (tableview...), mais seulement dans le cas simple d'un simple controller. Avec protocol, etc. Chose que j'ai bien assimilé dans le cas de mon etape0, mais pour le reste (pageView) on est dans le flou total.


     


    Maintenant si t'as un pur lien qui approfondit tout ça, je suis preneur, mais j'ai déjà  lu des tonnes de pages sur les protocol et delegate.


  • AliGatorAliGator Membre, Modérateur


    Maintenant si t'as un pur lien qui approfondit tout ça, je suis preneur, mais j'ai déjà  lu des tonnes de pages sur les protocol et delegate.

    Mon tutoriel de 2010 sur le sujet
  • Merci AliGator pour ton lien, mais malheureusement pour moi, il est en objC.


    J'arrive à  peu près à  traduire, car j'ai commencé en objC, mais j'avoue que ça me parait encore plus confus.


     


    Pour moi, le pb est simple :


     


    Je sais faire un truc delegate / protocole (excuse ma terminologie) sur (je le répète) un simple controller, mais cela ne marche pas sur un pageview.


     


    Donc, en gros, lorsqu'il existe déjà  des méthodes associées via le delegate (excuse ma terminologie), comment faire qu'il prenne la mienne - Comme dans le cas d'un simple controller qui n'a pas déjà  des méthodes associées via le delegate. Et dans ce cas, je le rappelle, je sais le faire.


     


    On fait quoi, on squizze le delegate du pageView, puis on fait le sien perso, comme l'explique Céroce



     


     


    Dans la délégation, un objet (délégateur) délègue une partie de son fonctionnement à  un autre objet (délégué).
    Dans ton cas, une instance de UIPageViewController délègue son fonctionnement à  une instance de Etape1ViewController.

    1) Il faut dire au délégateur qui sera son délégué:
     
    pageViewController.delegate = etape1ViewController

    2) Le délégateur va appeler des méthodes sur son délégué. Il est donc nécessaire de formaliser ces méthodes. C'est le rôle du protocole UIPageViewControllerDelegate qui définit ces méthodes. La doc d'Apple explique dans quelles circonstances ces méthodes sont appelées par le délégateur.

    De ton côté tu dois dire que Etape1ViewController se conforme à  ce protocole; c'est à  dire qu'il promet qu'il va implémenter ces méthodes.
    class Etape1ViewController: UIViewController, UIPageViewControllerDelegate

    { 3) Tu implémentes les méthodes voulues dans Etape1ViewController et elles doivent être appelées.

     


    ou bien on fait comme dans le cas d'un simple controller (chose que je maitrise), son propre delegate (comme dans ton tuto), et là , cela ne fonctionne pas dans le cas d'un pageView, et je suis sur que dans le cas d'un tableView, c'est la même.


     


    Mon problème est pourtant simple :


    Dans un cas (simple controller), ça marche, dans le cas d'un pageView, ça marche pas.


     


    Il est ou le problème ?


     


    C'est pas une histoire de concept ? Puisqu'il est assumé.


     


    Désolé pour le ton de dépité, mais je suis vraiment découragé, car pour moi cela doit être évident.


    Je sais faire un truc et je le comprend, et je n'y arrive plus dans un autre contexte, et surtout, je ne comprend pas pourquoi...

  • LexxisLexxis Membre
    mai 2015 modifié #31

    Dans le code posté je ne vois pas où est assigné la variable delegateEtape1 (tout comme Ali et Céroce te l'on dit). Cela me semble être un bon point de départ. Place un point d'arrêt sur:



    delegateEtape1?.configureNavbar?(self)

    et vérifie delegateEtape1 pour voir quel objet (et je parle d'objet pas de protocole) est assigné à  cette variable. Si cette variable est à  nil (ce qui semble être le cas) c'est qu'il manque la valorisation.


     


    Si cela fonctionne avec un 'simple controller' vérifie dans ton projet comment et où est assigné delegateEtape0.


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