Passer un objet d'une vue a une autre

TerflogagTerflogag Membre
mai 2014 modifié dans API UIKit #1

Hello,


 


je bloque dans le passage de donnée d'une vue à  une autre.


J'ai longtemps cherché sur le net, et j'ai notamment trouvé "PrepareForSegue" afin de passer des données. Si j'ai bien compris, "prepareForSegue" permet de passer des données d'une vue à  une autre (d'une vue A en push a une vue B par exemple).


Mon problème étant que je souhaiterai faire passer des données de la vue B à  la vue A.


 


Plus précisément, les 2 vues sont relié en Push (avec un Navigation Controller), je souhaiterai de ce fait envoyer des données dès que le bouton de retour de la vue B est pressé. Chose qui doit etre relativement simple, mais je n'ai pas réussie à  trouvé la réponse sur le net...


 


De façon plus simple, mon interface : 


- appuyer sur une cellule de A qui envoie sur B en push, lui meme composé d'un tableView


L'utilisateur "coche" un element du tableau, et lorsque il appuie sur retour afin de revenir sur A, les données de la cellule concerné de 1 doivent êtres modifiés. 


 


Autre question, mes deux vues sont de la meme classe, est ce un soucis ? Doit on avoir une classe par CV ?


 


Merci de votre aide !

Réponses

  • MayerickMayerick Membre
    juin 2014 modifié #2

    Bonjour,


     


    alors je vais tenter de te répondre car je suis aussi passé par là , j'en ai chié et j'aurais bien aimé trouvé une réponse comme ça. Ta question est assez simple ce qui explique qu'il n'y ait pas foule pour te répondre, et en même temps c'est assez difficile d'être clair. Je vais donc essayer. 


     


    La méthode prepareForSegue est effectivement la bonne. Mais il y a plusieurs choses à  faire avant de l'utiliser. Tu parles de tableView, as-tu bien implémenter le délégué ? ensuite l'idéal pour passer des données est de créer un protocole dans la classe de ton deuxième tableView.  Enfin Dans myFirstViewController il faut instancier un objet  UIStoryboardPopoverSegue *currentpopoverSegue;


    Dans storyBoard tu donnes un nom à  ton segue en cliquant dessus et en configurant tout cela dans le volet utilitaire de droite puis tu peux utiliser prepareForSegue en spécifiant le nom de ton segue si tu en as plusieurs, sinon il fera la même action quelque soit le segue.


     


    Selon moi tu dois avoir une classe pour chaque vue, mais peut-être que des plus expérimentées infirmerons cela. Niveau code je peux te proposer cela :  


    firstTableViewController.h



    #import <UIKit/UIKit.h>

    #import "SecondViewController.h"
    #import "Cell.h"
    @interface FirstTableViewController : UIViewController </*tes délégués*/>

    @property (strong, nonatomic) IBOutlet /*les objest de ta vue*/

    @end

    firstTableViewController.m



    #import "FirstViewController.h"
    @interface FirstView... ()
    {
    UIStoryboardPopoverSegue *currentPopoverSegue;
    SecondViewController *secondViewController;
    NSString *stringASauver;
    NSMutableArray *myFirstArray;
    }


    @end

    @implementation FirstView...{

    }

    @synthesize : ...

    // la méthode de ton protocole : // permet de rapatrier des données de la vue B vers la vue A
    -(void)onTableStringChoisie: (NSString *) string {

    [myButton setTitle:string forState:UIControlStateNormal]; /* ici je me sers de ce string
    pour configurer le titre d'un bouton, mais tu peux en faire ce que tu veux*/
    stringASauver = string;
    //ferme le popover une fois le choix effectué. // dans le cas d'un Popover, sinon inutile
    [currentPopoverSegue.popoverController dismissPopoverAnimated:YES];
    }

    // les méthodes obligatoires du délégué de la tableView de firstViewController
    //nombre de ligne tableview, soit le nombre d'objet

    -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return [myFirstArray count];
    }

    //retourne le nombre de section dans le tableau, comme réglage dans ios

    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    return 1;
    }
    // CUstomiser la cellule du taleview et mettre des données dedans.

    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
    static NSString *cellIdentifier = @CellIdentifier;
    Cel1 *cell = (Cel1 *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if (cell == nil) {
    UIViewController *c = [[UIViewController alloc] initWithNibName:@Cell bundle:nil];
    cell = (Cel1 *) c.view;
    }
    ...
    return cell;
    }

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    ...
    }

    //enfin passer des informations de la Vue A à  la vue B
    -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

    if([[segue identifier] isEqualToString:@popSeg]){
    currentPopoverSegue = (UIStoryboardPopoverSegue *)segue;
    secondViewController = [segue destinationViewController];
    secondViewController.tableDelegue = self;
    }



     


    dans SecondViewController.h : 



    #import <UIKit/UIKit.h>
    #import "Cell2.h"

    // Classe qui s'occupe des éléments de la vue du tableau

    //Declarer le protocole (toujours avec une Majuscule):

    @protocol TableDelegue <NSObject>

    //creer la méthode de ce protocole

    -(void)onTableStringChoisie:(NSString *)string;

    @end

    // abonnes-toi à  ma chaine de délégué pour vérifier les actions de cette classe:

    @interface SecondViewController : UIViewController
    <UITableViewDataSource, UITableViewDelegate>

    // instancier un objet issu de la classe de ce protocole

    @property (weak) id <TableDelegue> tableDelegue;

    @property (strong,nonatomic) /* les objets de ta vue s'il y'en a, comme un tableau par exemple */

    @end



     



     Enfin dans SecondViewController.m : tranquillou tu remets les méthodes obligatoires pour créer ton tableView, et à  la fin la méthode magique qui va repasser les infos de la vue B vers la vue A : 



    #import "SecondViewController.h"

    @interface SecondViewController (){
    NSMutableArray *myArray;
    }

    @end

    @implementation SecondViewController

    @synthesize: tableDelegue, myArray;

    //nombre de ligne tableview, soit le nombre d'objet

    -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return [myArray count];
    }

    //retourne le nombre de section dans le tableau, comme réglage dans ios

    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    return 1;
    }

    // CUstomiser la cellule du taleview et mettre des données dedans.

    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
    ....
    return cell;

    }

    -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    [tableDelegue onTableStringChoisie:[myArray objectAtIndex:indexPath.row]];
    }



    @end


    En espérant avoir été clair et que ça aide.



    Cordialement.


    [edit correction d'étourderies]


  • TerflogagTerflogag Membre
    juin 2014 modifié #3

    Bonjour, 


    Merci pour cette super explication ! Cela fonctionne a merveille, et grâce tes nombreux commentaires je pense avoir compris le principe.

     

    Un petit soucis persiste cependant, j'obtient un warning lorsque je fais :


    secondViewController.tableDelegue = self;


     


    Il s'agit visiblement d'un problème de typage : "Assigning to 'id<TableDelegate>' from incompatible type 'nomDuPremierController *const_strong'


    C'est  en effet la première fois que j'utilise une syntaxe tel que "id<TableDelegate>", je suis un peu perdu une nouvelle fois ! 


    Une idée ? 


     


    (sinon tout fonctionne parfaitement, mais me trimbaler un warning n'est jamais bon, d'autant plus lorsqu'on ne comprend pas l'erreur...)


  • Un peu de lecture et plus précisément ici ?


    À la base, si ta variable est typée avec un protocole <TonProtocole> taVariable alors tu dois avoir ce même protocole déclaré dans l'interface de la classe de taVariable.


    @Interface <TableDelegate>PremierController
     
    @end
    @Implementation PremierController
    - (void)maMethodeProtocoleObligatoire{
        return;
    }
    @end

    Un protocole sert à  déclarer qu'un objet possédera certaines méthodes. D'aucunes optionnelles, d'autres obligatoires.


    Si ta variable est déclarée comme respectant ce protocole sa classe doit l'avoir déclaré aussi dans son interface. Sinon ça passe avec un warning et ça fonctionne tant que la méthode appelée est présente..


  • Je n'aurais pas dis mieux, en tout cas je n'aurais pas retrouvé la doc. ^^


    Dans FirstViewController. je t'ai mis une ligne :



    @interface FirstTableViewController : UIViewController </*tes délégués*/>

    "tes délégués" fait référence à  tous les délégués auxquels ta classe doit se conformer et répondre. Donc tous les objets qui nécessitent un délégué (UITextField, UIScrollView, UIPicker...) doivent spécifier à  la classe de faire attention aux actions qu'ils permettent. C'est justement sur cette ligne @interface que tu spécifies les protocoles qui intègrent les méthodes obligatoires et optionnelles relatives aux délégués. Si j'ai bien compris tu as un tableView dans ta vue, de plus tu aimerais que ta classe se conforme à  ton custom protocole, donc il faut le spécifier : 



    @interface FirstTableViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, TableDelegue /*, plus tous ceux dont peux avoir besoin*/>

    J'ai fais exprès de l'appeler TableDelegue et non TableDelegate car au début c'était assez flou pour moi et je trouvais que ça ressemblait trop à  UITableViewDelegate, mais bien sûr le nom est libre.


     


    En espérant que ça aide.


    Bon courage.


  • Merci pour ces réponses, tout est plus clair maintenant. Et oui effectivement je devrais me reporter plus souvent à  la doc... Et surtout améliorer mon anglais  :P


  • Bonjour,


    J'ai le même problème, mais je n'ai pas de storyboard, j'essaie de tout faire en mode programmatique.

    Voici mon souci.

    J'essaie de créer une application basée sur un tabbarcontroller qui gère deux view contrôler : un pour créer un tableau d'épingles ("stepCollection") sur une mapview, l'autre pour faire apparaà®tre au fur et à  mesure ces épingles via le tableau que j'ai crée dans le premier que j'aimerais faire pointer par mon objet "stepCollectionP"v. Mes épingles sont des instances d'une classe que j'ai crée (comme les étapes d'une chasse au trésor) et sont collectées dans un objet défini par une classe qui l'englobe.

    Mon problème est que je n'arrive pas à  mettre mon objet stepCollection dans mon autre objet stepCollectionP.

    Auriez vous une idée?

    Merci de votre aide.


    Mickael
  • Alors il me semble qu'il y a plusieurs solution la première est de récupérer ton second viewController via ta tabBar un genre de [self.tabBarController controllerAtIndex:1] c'est pas la ligne de code exacte mais ça devrait ressembler à  ça.


     


    Ensuite tu pourrais notifier le changement via le notification center en passant ton objet.


     


    Sinon tu peux enregistrer ton objet en local dans le device et le recuperer quand tu arrives sur ton second viewController


     


    Tu peux éventuellement faire un délégué bien que je trouve pas ça très classe avec un tabBarController il faudrait déclarer tout ça dans le delegate je sais pas ça marcherait potentiellement mais je trouve pas ça super beau.


     


    En fait la difficulté de ton problème par rapport à  celui d'avant c'est que pour le problème du dessus A déclare B et le pousse ils sont en quelques sorte lié mais pour toi A et B sont créé en même temps et sont contenu en parallèle dans la tabBar. Du coup tu profitera pas du cycle de vie (init -> viewWillAppear -> ....) donc il faut recharger les données en temps réel. Pour moi la notification tient la route dans ce cas la. Je sais pas si c'est la meilleurs solution ceci dit.


  • Merci bcp je vais tenter ta solution sur les notifications.


  • J'ai essayé d'implémenter dans mon appdelegate dès que je choisis mon deuxième tabBar (didSelectViewController) :


     


    if (viewController==tvc) {


    [tvc gameView] stepCollectionP] setStepCollectionObject:[[tbc creationView] stepCollection;


    };


     


    Rien n'y fait. Je suis perplexe. Mon stepCollectionP dans mon tbc(2° view controller de mon tabBar) est toujours à  nil.


  • Joanna CarterJoanna Carter Membre, Modérateur
    juillet 2014 modifié #11

    J'ai une démarche alternative qui peut vous intéresser.


     


    En utilisant le blocks on peut simplifier le code un peu. J'ai mis un projet téléchargeable sur mon site à  http://carterconsulting.org.uk/Examples/TransmissionDeDonn%C3%A9es.zip


     


    Ici, se trouve l'essentiel...



    //
    // RootViewController.m
    // TransmissionDeDonnées
    //
    // Created by Joanna Carter on 10/07/2014.
    // Copyright (c) 2014 Carter Consulting. All rights reserved.
    //


    #import "RootViewController.h"
    #import "DetailViewController.h"
    #import "Article.h"


    typedef NS_ENUM(NSUInteger, RowIndex)
    {
    RowIndexNom,
    RowIndexPrix,
    RowIndexTva,
    RowCount
    };


    @interface RootViewController ()

    @property (strong, nonatomic) Article *selectedArticle;

    @end


    @implementation RootViewController

    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
    return RowCount;
    }

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
    UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];

    cell.detailTextLabel.text = self.selectedArticle.nom;

    return cell;
    }

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {
    switch ((RowIndex) indexPath.row)
    {
    case RowIndexNom:
    {
    DetailViewController *detailViewController = [self.storyboard instantiateViewControllerWithIdentifier:@Detail View Controller];

    __weak typeof(self) weakSelf = self;

    detailViewController.didSelectArticle = ^(Article *article)
    {
    weakSelf.selectedArticle = article;

    [tableView reloadRowsAtIndexPaths:@[;indexPath] withRowAnimation:UITableViewRowAnimationNone];

    [weakSelf.navigationController popViewControllerAnimated:YES];
    };

    [self.navigationController pushViewController:detailViewController animated:YES];
    }
    break;

    case RowIndexPrix:
    {

    }
    break;

    case RowIndexTva:
    {

    }
    break;

    case RowCount:
    @throw [NSException exceptionWithName:NSRangeException reason:@Tentatif d'accéder rang pour RowCount userInfo:nil];
    }
    }

    @end


    //
    // DetailViewController.h
    // TransmissionDeDonnées
    //
    // Created by Joanna Carter on 10/07/2014.
    // Copyright (c) 2014 Carter Consulting. All rights reserved.
    //


    @class Article;


    @interface DetailViewController : UITableViewController

    - (void)setSelectedArticle:(Article *)selectedArticle;

    @property (copy, nonatomic) void (^didSelectArticle) (Article *article);

    @end


    //
    // DetailViewController.m
    // TransmissionDeDonnées
    //
    // Created by Joanna Carter on 10/07/2014.
    // Copyright (c) 2014 Carter Consulting. All rights reserved.
    //


    #import "DetailViewController.h"
    #import "Article.h"


    @interface DetailViewController ()

    @property (strong, nonatomic) NSArray *articles;

    @property (strong, nonatomic) Article *selectedArticle;

    @end


    @implementation DetailViewController

    - (void)viewDidLoad
    {
    [super viewDidLoad];

    self.articles = @[;
    [[Article alloc] initAvecNom:@Une],
    [[Article alloc] initAvecNom:@Deux],
    [[Article alloc] initAvecNom:@Trois],
    [[Article alloc] initAvecNom:@Quatre]
    ];
    }

    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
    return self.articles.count;
    }

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@DetailCell forIndexPath:indexPath];

    Article *article = self.articles[indexPath.row];

    cell.textLabel.text = article.nom;

    if ([self.selectedArticle.nom isEqualToString:article.nom])
    {
    cell.accessoryType = UITableViewCellAccessoryCheckmark;
    }
    else
    {
    cell.accessoryType = UITableViewCellAccessoryNone;
    }

    return cell;
    }

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {
    self.didSelectArticle(self.articles[indexPath.row]);
    }

    @end

  • Merci pour toute cette aide.


    J'ai bien peur d'être obligé d'ajouter un navigation contrôler au final. Tous les exemples que je trouve en ont un.

  • Joanna CarterJoanna Carter Membre, Modérateur
    juillet 2014 modifié #13


    J'ai le même problème, mais je n'ai pas de storyboard, j'essaie de tout faire en mode programmatique.




     


    Mais pourquoi ? C'est un parcours assez lourd !


     




    Merci pour toute cette aide.


    J'ai bien peur d'être obligé d'ajouter un navigation contrôler au final. Tous les exemples que je trouve en ont un.




     


    Parce que c'est la bonne route. Sinon, c'est beaucoup plus de travaille pour réaliser le même but


     


    Je viens de voir que tu utilises un tab bar controller, du coup, voir mon prochain message


  • Joanna CarterJoanna Carter Membre, Modérateur


    J'essaie de créer une application basée sur un tabbarcontroller qui gère deux view contrôler : un pour créer un tableau d'épingles ("stepCollection") sur une mapview, l'autre pour faire apparaà®tre au fur et à  mesure ces épingles via le tableau que j'ai crée dans le premier que j'aimerais faire pointer par mon objet "stepCollectionP"v. Mes épingles sont des instances d'une classe que j'ai crée (comme les étapes d'une chasse au trésor) et sont collectées dans un objet défini par une classe qui l'englobe.

    Mon problème est que je n'arrive pas à  mettre mon objet stepCollection dans mon autre objet stepCollectionP.




     


    Est-ce que tu as un modèle que les deux view controllers puissent voir au même temps ?


     


    Si oui, est-ce que tu lis les données de cet modèle, dans les view controllers, pour actualiser les deux vues ?


     


    Donc, il faut créer une notification qui est provoqué pendant la méthode qui reçoit le message de change dans n'importe quelle view controller.


     


    Puis, ce notification s'accroche dans les deux view controllers, afin que tu puisses mettre à  jour la vue.


     


    ça c'est le MVC (Modèle Vue Contrôleur)  :-*

  • Mon modèle est constitué d'une classe représentant les étapes de la chasse au trésor et d'une autre classe qui est en fait un MutableArray de ces étapes (stepCollection).


    Mon premier controller gère une instance stepCollection pour stocker les différentes étapes que je crée via la vue (MapView) géré par ce controller.


    Le deuxième controller déclare dans sa vue une autre instance (stepCollectionP). Est-ce que je devrais tout déclare dans le AppDelegate pour avoir une seule instance accessible par les deux controller?


    Ca ne me semble pas être la bonne solution car cela revient à  avoir une instance globale non?

  • Joanna CarterJoanna Carter Membre, Modérateur
    juillet 2014 modifié #16


    Mon modèle est constitué d'une classe représentant les étapes de la chasse au trésor et d'une autre classe qui est en fait un MutableArray de ces étapes (stepCollection).


    Mon premier controller gère une instance stepCollection pour stocker les différentes étapes que je crée via la vue (MapView) géré par ce controller.


    Le deuxième controller déclare dans sa vue une autre instance (stepCollectionP). Est-ce que je devrais tout déclare dans le AppDelegate pour avoir une seule instance accessible par les deux controller?


    Ca ne me semble pas être la bonne solution car cela revient à  avoir une instance globale non?




     


    Pas de soucis ;-)


     


    Si tu déclarais une instance comme un @property dans le AppDelegate, elle ne serait pas globale, elle serait membre de la classe. Rien ne t'empêche de passer une référence de cette instance aux deux controllers.


  • Ok mais comment faire pour y accéder.

    Est-il autorise d'accéder à  l'appdelegate dans les sous vues?
  • samirsamir Membre
    juillet 2014 modifié #18

    Si tu veux faire simple pour l'instant :


     


    Le UITabController contient la liste des contrôleurs qui sont actuellement affichés dans un array. Donc tu récupère celui qui t'intéresse avec l'index. L'index 0 correspond au contrôleurs le plus à  gauche ( le premier) et ainsi de suite.


     


    un truc de genre :



    TonViewController *vc = (TonViewController *)self.tabBarController.viewController[0];

    viewControllers

    An array of the root view controllers displayed by the tab bar interface.



    @property(nonatomic, copy) NSArray *viewControllers


    Discussion

    The default value of this property is nil. When configuring a tab bar controller, you can use this property to specify the content for each tab of the tab bar interface. The order of the view controllers in the array corresponds to the display order in the tab bar. Thus, the controller at index 0 corresponds to the left-most tab, the controller at index 1 the next tab to the right, and so on. If there are more view controllers than can fit in the tab bar, view controllers at the end of the array are managed by the More navigation controller, which is itself not included in this array.



    If you change the value of this property at runtime, the tab bar controller removes all of the old view controllers before installing the new ones. The tab bar items for the new view controllers are displayed immediately and are not animated into position. When changing the view controllers, the tab bar controller remembers the view controller object that was previously selected and attempts to reselect it. If the selected view controller is no longer present, it attempts to select the view controller at the same index in the array as the previous selection. If that index is invalid, it selects the view controller at index 0.



  • Joanna CarterJoanna Carter Membre, Modérateur

    Il n'est pas interdit d'accéder l'AppDelegate mis il est fortement déconseillé  :*


     


    Comment crées-tu les view controllers et les ajoutes au tab controller ? En code ou depuis un storyboard ?


  • C'est pour ça que je posais la question car le principe me semblait violent et ne me plaisait pas.


    Je crée tout en programmatique sur les conseils d'un MOOC que j'ai suivi (plateforme FUN, MOOC de l'UPMC)...Au final, quand je fais des recherches sur internet, je vois tellement d'utilisation de storyboard qui a l'air tellement plus sympa en plus! bref, je crée les les viewcontroller dans le appdelegate, les insère dans un tableau que j'assigne à  viewcontrollers du tabBarcontroller. Ensuite, j'ai un viewcontroller pour mes deux ongles qui contiennet chacun une vue différente définie aussi en code.


  • Joanna CarterJoanna Carter Membre, Modérateur
    juillet 2014 modifié #21


    C'est pour ça que je posais la question car le principe me semblait violent et ne me plaisait pas.




     


    ::)


     




    Je crée tout en programmatique sur les conseils d'un MOOC que j'ai suivi (plateforme FUN, MOOC de l'UPMC)...Au final, quand je fais des recherches sur internet, je vois tellement d'utilisation de storyboard qui a l'air tellement plus sympa en plus! bref, je crée les les viewcontroller dans le appdelegate, les insère dans un tableau que j'assigne à  viewcontrollers du tabBarcontroller. Ensuite, j'ai un viewcontroller pour mes deux ongles qui contiennet chacun une vue différente définie aussi en code.




     


    Ouahouh ! Un MOOC qui n'enseigne pas les storyboards ? C'est du Moyen à‚ge !


     


    Les storyboards, ou même les XIB sont beaucoup plus efficaces et, surtout, plus faciles.


     


    Je ne peux pas démontrer comment faire le storyboard ici, mais voici quelques extraits de code que l'on puisse utiliser avec un storyboard...



    //
    // ViewControllerPourEtapes.h
    // TabTest
    //
    // Created by Joanna Carter on 11/07/2014.
    // Copyright (c) 2014 Carter Consulting. All rights reserved.
    //


    @protocol ViewControllerPourEtapes <NSObject>

    @property (weak, nonatomic) NSMutableArray *etapes;

    @end


    //
    // FirstViewController.h
    // TabTest
    //
    // Created by Joanna Carter on 11/07/2014.
    // Copyright (c) 2014 Carter Consulting. All rights reserved.
    //


    #import "ViewControllerPourEtapes.h"


    @interface FirstViewController : UIViewController <ViewControllerPourEtapes>

    @end


    //
    // FirstViewController.m
    // TabTest
    //
    // Created by Joanna Carter on 11/07/2014.
    // Copyright (c) 2014 Carter Consulting. All rights reserved.
    //


    #import "FirstViewController.h"


    @interface FirstViewController ()

    @end


    @implementation FirstViewController


    @synthesize etapes = _etapes;

    - (void)viewDidLoad
    {
    [super viewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.
    }

    @end


    //
    // SecondViewController.h
    // TabTest
    //
    // Created by Joanna Carter on 11/07/2014.
    // Copyright (c) 2014 Carter Consulting. All rights reserved.
    //


    #import "ViewControllerPourEtapes.h"


    @interface SecondViewController : UIViewController <ViewControllerPourEtapes>

    @end


    //
    // SecondViewController.m
    // TabTest
    //
    // Created by Joanna Carter on 11/07/2014.
    // Copyright (c) 2014 Carter Consulting. All rights reserved.
    //


    #import "SecondViewController.h"


    @interface SecondViewController ()

    @end


    @implementation SecondViewController

    @synthesize etapes = _etapes;

    - (void)viewDidLoad
    {
    [super viewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.
    }

    @end


    //
    // AppDelegate.m
    // TabTest
    //
    // Created by Joanna Carter on 11/07/2014.
    // Copyright (c) 2014 Carter Consulting. All rights reserved.
    //


    #import "AppDelegate.h"
    #import "ViewControllerPourEtapes.h"


    @interface AppDelegate ()

    @property (strong, nonatomic) NSMutableArray *etapes;

    @end


    @implementation AppDelegate

    - (NSArray *)etapes
    {
    if (!_etapes)
    {
    _etapes = [NSMutableArray array];
    }

    return _etapes;
    }

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
    UITabBarController *tbc = (UITabBarController *) self.window.rootViewController;

    for (id<ViewControllerPourEtapes> viewController in tbc.viewControllers)
    {
    viewController.etapes = self.etapes;
    }

    return YES;
    }

    @end

    Si tu voulais, je pourrait t'envoyer le projet basique complet.


  • Joanna CarterJoanna Carter Membre, Modérateur

    Si tu préfères rester en code, voici l'AppDelegate presque pareil...



    //
    // AppDelegate.m
    // TabTest
    //
    // Created by Joanna Carter on 11/07/2014.
    // Copyright (c) 2014 Carter Consulting. All rights reserved.
    //


    #import "AppDelegate.h"
    #import "ViewControllerPourEtapes.h"


    @interface AppDelegate ()

    @property (strong, nonatomic) NSMutableArray *etapes;

    @end


    @implementation AppDelegate

    - (NSArray *)etapes
    {
    if (!_etapes)
    {
    _etapes = [NSMutableArray array];
    }

    return _etapes;
    }

    - (BOOL)application:(UIApplication *)app didFinishLaunchingWithOptions:(NSDictionary *)optionsDict
    {
    id<ViewControllerPourEtapes> firstVC = [[FirstViewController alloc] init];

    firstVC.etapes = self.etapes;

    id<ViewControllerPourEtapes> secondVC = [[SecondViewController alloc] init];

    secondVC.etapes = self.etapes;

    UITabBarController *tbc = [[UITabBarController alloc] init];

    [tbc setViewControllers:@[;firstVC, secondVC]];

    [window setRootViewController:tbc];

    [window makeKeyAndVisible];

    return YES;
    }
  • MayerickMayerick Membre
    juillet 2014 modifié #23
    /* apparté :


    Pour avoir suivi ce MOOC également puis abandonné vers la fin, c'est clair que la ligne pédagogique est préhistorique. J'ai fait remonter ça dans le questionnaire et autres, mais le ton de l'équipe pédagogique concernant ARC et storyboard est ultra pédant et conservateur, ceux qui l'ont suivi comprendront bien.


    */
  • Je suis assez d'accord avec toi Mayerick. J'ai fait tous les exercices sauf le dernier en utilisant ARC car si Apple a implémenté ce concept ce n'est pas pour rien.


    Storyboard est en plus un outil assez sympa et les cours du Big Nerd Ranch ou de Stanford s'appuient dessus, selon moi gage de sérieux...


    Bref, concernant les vues, l'aspect programmatique était assez bien pour comprendre comment cela marchait (mon expérience est assez réduite j'ai débuté l'objective-c il y a 4 mois) mais du coup cela me prive de fonctionnalités pourtant intéressante.


    Merci Joanna pour ton exemple, je regarde ça de suite.


  • J'ai fini par craquer: j'ai rajouté un navigation controller. Je pousse ma deuxième vue après appui sur un bouton.

    Pour autant, je n'arrive pas a passer mon objet à  ma deuxième vue. Son objet stepcollection reste à  nil malgre ma ligne de code pour lui transmettre les mêmes infos que l'objet de la première vue. Quelqu'un aurait une idée?
  • Joanna CarterJoanna Carter Membre, Modérateur


    J'ai fini par craquer: j'ai rajouté un navigation controller. Je pousse ma deuxième vue après appui sur un bouton.




     


     


    Mais pourquoi ? Tu as commencé en créant un app tab bar dont il n'y a aucune nécessité d'ajouter un navigation controller pour accomplir ce que tu voulais.


     


     




    Pour autant, je n'arrive pas a passer mon objet à  ma deuxième vue. Son objet stepcollection reste à  nil malgre ma ligne de code pour lui transmettre les mêmes infos que l'objet de la première vue. Quelqu'un aurait une idée?




     


    Est-ce que tu peux nous afficher le code, que tu as fait, qui crée les deux controllers ?

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