# [iOS] Problème delegate



## BenArko (23 Octobre 2012)

Bonjour,

j'ai défini le protocole suivant dans la classe CreationTacheViewController :


```
@interface CreationTacheViewController : UIViewController <UITextViewDelegate>

@property (nonatomic, assign) id <CreateTacheDelegate> delegate;
...
@end

@protocol CreateTacheDelegate <NSObject>
- (void)createTacheController:(CreationTacheViewController *)controller didCreateTache:(Tache *)tache;
@end

et j'utilise  ce protocole dans la classe TacheViewController où je définis la méthode comme suis :

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"creationTache"])
    {
        _creationTacheViewController = [[CreationTacheViewController alloc] init];
        _creationTacheViewController.delegate = self;
    }
}

- (void)createTacheController:(CreationTacheViewController *)controller didCreateTache:(Tache *)tache
{
    tache.projet = _projet;
    [_projet.managedObjectContext save:nil];
    [_tacheArray addObject:tache];
    [self.tableView reloadData];
}
```
Le problème c'est qu'une fois dans l'exécution du code de la classe  CreationTacheViewController l'objet delegate est a nil ce qui fait que  la méthode createTacheController didCreateTache n'est pas appelé, je voudrais donc savoir comment faire pour que l'objet delegate ne soit pas null.

merci d'avance


----------



## ntx (23 Octobre 2012)

Est-ce que tu es sûr que ton code passe sur la ligne "_creationTacheViewController.delegate = self;" avant de vouloir utiliser ton delegate ?


----------



## BenArko (23 Octobre 2012)

Oui la ligne de code est bien exécuté.


----------



## ntx (24 Octobre 2012)

Et les adresses des deux objets sont bien les mêmes ?


----------



## BenArko (24 Octobre 2012)

Non les adresses des deux objets ne sont pas les mêmes. Je pense que l'objet _creationViewController est supprimé une fois que la méthode PrepareForSeque est exécutée. Sinon j'ai essayé ceci :


```
//TacheViewController.m
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"creationTache"])
    {
        _creationTacheViewController = [[CreationTacheViewController alloc] initWithDelegate:self];
    }
}

//CreationTacheViewController.m
- (id)initWithDelegate:(id)p_delegate
{
    self = [super init];
    if( self )
    {
        self.delegate = p_delegate;
    }
    return self;
}
```
Si besoin de plus de code ne pas hésiter à demander et je peux même fournir le projet entier si ça peut aider.


----------



## ntx (24 Octobre 2012)

Regarde la façon dont ton objet controller est créé. Ne l'aurais-tu pas créé à la fois dans interface builder et dans ton code ? Et donc tu n'utiliserais pas la bonne instance.


----------



## BenArko (25 Octobre 2012)

Comment peut on voir la façon dont l'objet du controller est créé ? Et comment peut on créer une instance dans interface builder ?


----------



## Larme (25 Octobre 2012)

Manquerait pas un retain sur ton objet, vu que tu dis qu'il te semble qu'il est supprimé ?


----------



## BenArko (25 Octobre 2012)

j'utilise l'ARC donc je peux pas faire de retain


----------



## ntx (25 Octobre 2012)

BenArko a dit:


> Et comment peut on créer une instance dans interface builder ?


Dans le vue "Objects" tu peux ajouter des instances des classes que tu trouves dans "Objects & Controller". Il suffit ensuite de les référencer comme "Outlet" dans un objet que ce dernier puisse l'utiliser.


----------



## BenArko (26 Octobre 2012)

au vu de tes explications je peux te dire que je n'ai pas créé d'instance par le biais d'interface builder et donc normalement il devrait y en avoir qu'une seule. Sinon je c'est pas si ça peut aider mais dans la partie qui me pose problème pour arriver sur le view controller CreateTacheViewController j'utilise une transition en mode "modal" qui "arrive sur un navigation controller qui est lui même relier par une liaison de type relationship à mon view controller CreateTacheViewController.


----------



## BenArko (16 Novembre 2012)

Personne n'a d'idée ? Sinon pour ce faire une idée plus précise de l'appli et donc du problème voici toute mon projet : ici

merci d'avance


----------



## ntx (16 Novembre 2012)

BenArko a dit:


> donc normalement il *devrait* y en avoir qu'une seule.


Il devrait y avoir plus de certitudes


----------



## BenArko (17 Novembre 2012)

C'était un conditionnel affirmatif , en d'autres termes il n'y a qu'une seule instance .


----------



## ntx (17 Novembre 2012)

> Non les adresses des deux objets ne sont pas les mêmes.


Ce problème a été résolu ?


----------



## BenArko (17 Novembre 2012)

Ba non c'est ça le probléme c'est que les deux variables ne sont pas les mêmes, le premier que je créé dans la méthode prepareForSegue est supprimé une fois que la méthode est terminée. Puis une nouvelle est crée mais son delegate n'est pas initialisé ce qui fait que je ne peux pas utiliser le delegate que j'ai créé dans la classe CreationTacheViewController.


----------



## ntx (17 Novembre 2012)

Si tu mets un point d'arrêt dans le constructeur de ton contrôleur, est-ce que ton programme y passe une fois ou deux fois ?


----------



## BenArko (17 Novembre 2012)

Une fois.

Pour Rappel voici mon constructeur et son appel

appel du constructeur dans la classe TacheViewController :


```
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"creationTache"])
    {
        self.creationTacheViewController = [[CreationTacheViewController alloc] initWithDelegate:self];
    }
}
```
constructeur de la classe CreationTacheViewController :


```
- (id)initWithDelegate:(id)p_delegate
{
    self = [super init];
    if( self )
    {
        self.delegate = p_delegate;
    }
    return self;
}
```


----------



## ntx (17 Novembre 2012)

Et si tu surchagres le constructeur par défaut de la classe mère, est-ce que tu passes dedans ?


----------



## BenArko (18 Novembre 2012)

La classe mère c'est NSObject donc je pense pas que je puisse la surcharger.


----------



## ntx (18 Novembre 2012)

Tu mets dans ta classe une fonction "- (id)init" et tu vois quand le programme passe dedans.


----------



## BenArko (18 Novembre 2012)

je vois pas trop quoi mettre dedans, j'ai déjà essayé dinitialiser le delegate dans la méthode viewDidLoad et j'ai eu une flopée d'erreur.


----------



## ntx (18 Novembre 2012)

tu fais un return [super init];

C'est juste pour pouvoir mettre le point d'arrêt du debugeur.


----------



## BenArko (18 Novembre 2012)

On y passe jamais.


----------



## ntx (18 Novembre 2012)

Donc tu me dis que tu as deux instances de ta classe alors que tu ne passes qu'une seule fois dans un constructeur ... J'ai comme un doute ...  Pas d'autre constructeur pour ta classe ?


----------



## BenArko (19 Novembre 2012)

Bonne nouvelle (surtout pour moi ) sur un autre forum quelqu'un a trouvé la solution !!

Le problème venait du fait que ma transition arrivait sur un navigationController et non directement sur sur mon CreationTacheViewController. Donc pour résoudre le problème il faut que dans dans la méthode prepareForSegue, il faut setter le delegate du destinationViewController. Aussi, le destinationViewController est un navigationviewcontroller dans mon cas, du coup il faut récupérer le premier viewController du navigationController pour accéder au delegate de CreationTachesViewController.

donc voici a quoi ressemble la méthode prepareForSegue de la classe TacheViewController (classe d'où "part" la transition) :


```
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"creationTache"])
    {
        UINavigationController *controller = segue.destinationViewController;
        ((CreationTacheViewController *)[controller.viewControllers objectAtIndex:0]).delegate = self;
    }
}
```
Et hop ça fonctionne  !!!

merci a tous pour votre aide


----------

