2009-10-02 9 views
1

Ceci est une question Objective-C/iphone SDK.Objective-C: solution élégante à la création conditionnelle d'objets?

J'ai une vue de tableau de bord qui est utilisée pour passer à différentes vues dans mon application. Essentiellement la vue a six boutons qui raccourcissent à une vue différente.

Voici un exemple du code de gestion des événements de bouton:

- (IBAction)moreButtonPressed:(id)sender{ 
// switch view here 
if(self._moreViewController == nil){ 
    MoreViewController *moreViewController = [[MoreViewController alloc] initWithNibName:@"MoreView" bundle:[NSBundle mainBundle]]; 
    self._moreViewController = moreViewController; 
    [moreViewController release]; 
} 

[self SwitchView:self._moreViewController]; 
} 

Je peux dupliquer ce code pour chaque bouton et modifier les classes appropriées (voir les classes de contrôleur)), mais j'aimerais une solution plus élégante .

Est-ce que quelqu'un a une idée de la façon de faire cela?

Répondre

4

D'abord, déplacer le nom de la BNI dans la classe ViewController avec un code tel que:

- (MoreViewController *)init 
{ 
    self = [super initWithNibName:@"MoreView" bundle:nil]; 
    if (self != nil) 
    { 
    } 
    return self; 
} 

Cela rendra votre vue des contrôleurs autonome afin que vous puissiez les créer proprement:

MoreViewController *moreViewController = [[MoreViewController alloc] init]; 

Je recommande cette approche, peu importe ce que vous faites d'autre. L'exemple de code d'Apple nonobstant, il est stupide de mettre le nom de la NIB dans l'appelant. Pourquoi chaque appelant d'un contrôleur de vue doit-il connaître ce détail d'implémentation interne?

Ensuite, rappelez-vous que ObjC est un langage dynamique. Vous pouvez construire des objets en fonction de leur classe nom comme ceci:

Class vcClass = NSClassFromString([self.classNameForSender objectForKey:sender]) 
UIViewController *vc = [[[vcClass alloc] init] autorelease]; 
[self switchToView:vc]; 

Dans ce qui précède, -classNameForSender est une NSDictionary qui mappe les objets bouton au nom de la classe, mais vous pouvez obtenir ces noms de classe beaucoup d'autres façons bien sûr. En fonction de l'expéditeur, vous pouvez être en mesure d'accrocher la classe directement sur l'expéditeur (bien que cela soit difficile avec la norme UIControl car ils n'ont qu'un nombre entier de tag).

Je n'ai pas dupliqué votre stockage du VC dans un ivar. Avez-vous vraiment besoin de cela? Si c'est le cas, vous pouvez le stocker dans un dictionnaire par son nom ou vous pouvez stocker tous les VC dans un NSMutableSet. Mais dans la plupart des cas, vous n'avez vraiment pas besoin de cela puisque la plupart des contrôleurs d'interface utilisateur (comme NavController) gèrent la mémoire pour vous.

Une autre approche moins dynamique consiste à créer tous les contrôles de vue au début et les mettre dans un dictionnaire, puis vous pouvez simplement les charger dans le dictionnaire en fonction de l'expéditeur. Cela a l'avantage de mieux vérifier les temps de compilation, mais peut manger beaucoup plus de mémoire.

0

Une simple amélioration serait de définir la propriété de balise pour chaque bouton lors de sa création puis

 
- (IBAction)someButtonPressed:(id)sender{ 
// switch view here 

switch (sender.tag) { 
case 0: 
if(self._moreViewController == nil){ 
    MoreViewController *moreViewController = [[MoreViewController alloc] initWithNibName:@"MoreView" bundle:[NSBundle mainBundle]]; 
    self._moreViewController = moreViewController; 
    [moreViewController release];} 
[self SwitchView:self._moreViewController]; 
break; 
case 1: 
if(self._lessViewController == nil){ 
    MoreViewController *lessViewController = [[LessViewController alloc] initWithNibName:@"LessView" bundle:[NSBundle mainBundle]]; 
    self._lessViewController = lessViewController; 
    [lessViewController release];} 
[self SwitchView:self._lessViewController]; 
break; 
} 

} 

cette façon, vous ne disposez que d'une fonction. Cependant, il serait bien de ne pas répéter le code dans une instruction case et de fournir simplement un paramètre de la classe à instancier. Ce n'est pas quelque chose que j'ai essayé cependant.

Questions connexes