2009-05-26 6 views
3

Exemple:Comment puis-je créer dynamiquement une instance d'une classe?

j'ai 10 vue contrôleurs, qui sont tous attribués et initialisé de la même façon:

UIViewController *controller = [[MyViewController alloc] initWithNib]; 

(noter que -initWithNib est une méthode personnalisée d'une sous-classe UIViewController)

La classe de contrôleur de vue suivante est OtherViewController, et ainsi de suite. Je veux charger les contrôleurs de vue paresseusement, juste quand j'en ai besoin. Mais pour ce faire, j'ai besoin d'une sorte de "tableau" qui me donnera la classe correspondante pour un index donné, afin que je puisse l'initialiser.

J'ai fini par créer une méthode avec une grosse instruction de commutateur, qui fera juste cette allocation désagréable et initialisation séparément pour chaque contrôleur de vue unique. Je ne suis pas content avec ça. Là, il serait beaucoup mieux si je pouvais assigner la classe appropriée à une variable, puis à la fin de l'instruction switch juste allouer et initialiser cette classe à partir de la variable.

Existe-t-il un moyen d'y parvenir?

EDIT: J'ai trouvé une fonction

id class_createInstance(Class cls, size_t extraBytes) 

et chaque classe semble avoir une propriété « classe ». Mais je ne peux pas l'assigner à une variable d'instance. Cela ne fonctionne pas:

Class cls = [UIImage class]; 
cls *image = [cls imageNamed:@"avatar.png"]; 

La première ligne est compilée. Mais le second donne une erreur: "image non déclarée".

+3

On dirait une copie exacte de http://stackoverflow.com/questions/381793 – smorgan

+1

J'ai modifié ma réponse pour inclure un motif de base. Vous voudriez faire: id image = [cls imageNamed: @ "avatar.png"]. Cependant, il est préférable d'utiliser un type de base commun ici (c'est-à-dire UIImage * image = ...) car la première partie de votre question indique que c'est le cas. – Jason

Répondre

13

Si vous connaissez les noms des classes à la compilation, vous pouvez assigner les classes aux variables de classe. Par exemple:

static Class factory[2]; 

factory[0] = [MyViewController1 class]; 
factory[1] = [MyViewController2 class]; 
... 

alors vous pourriez avoir (classid serait une constante connue au moment de la compilation qui tracerait à une classe souhaitée:

-(UIViewController*)createViewController:(int)classid 
{ 
    return [[factory[classid] alloc] init]; 
} 

En supposant que la méthode est définie dans une classe nommée myFactory, vous pouvez alors faire:

MyFactory * fac = [[MyFactory alloc] init]; 
UIViewController * v1 = [fac createViewController: 0]; // typed 
id v2 = [fac createViewController: 1]; // untyped 

Si vous n'avez pas le nom de compilation de la classe, vous pouvez simplement faire ce qui suit:

#include <objc/objc-runtime.h> 

id object = [[NSClassFromString(@"TheClassName") alloc] init]; 

Comme votre question initiale implique un ensemble de UIViewControllers, il n'y a aucune raison de perdre la sécurité de type avec la dernière méthode.

0

Ce que vous voulez, c'est Reflection. Aucune idée de l'objectif-c l'a cependant - mais le terme pourrait vous aider à mieux répondre à Google.

+0

-1 ??? Donnez-moi une pause - c'est une réponse complètement correcte et était aussi la seule réponse au début après une heure. Juste parce que vous ne connaissez pas une langue spécifique ne signifie pas qu'une réponse est incorrecte - cela aurait très bien pu aider un autre utilisateur à répondre à la question. Certaines personnes sur ce site doivent se prendre au sérieux ou trouver un nouveau passe-temps. – Gandalf

+1

Il y a toujours des gens qui vont voter pour une réponse qu'ils considèrent comme impropre pour une raison quelconque. Vous obtenez beaucoup plus de crédit pour un upvote qu'un downvote vous coûte. Ne le laissez pas vous déranger, c'est mauvais pour la tension artérielle. – mmc

6

Vous voulez utiliser la réflexion:

id controller = class_createInstance(NSClassFromString(@"your class name"), 0/*extra bytes*/); 

Objective-C Runtime Reference

+0

Je reçois un avertissement: "déclaration implicite de la fonction 'class_createInstance'" – Thanks

+1

#import

+0

@arul, est-il possible de faire [[NSClassFromString (@ "MyClass") alloc] init ]? –

0

La référence Objectif C sera un bon endroit aussi chercher à obtenir les appels. Essayez de rechercher Objective-C 2.0 Runtime Référence puisque je ne peux pas ajouter de liens

1

Je blogué sur ce dernier mois à: http://igotosoft.blogspot.com/2009/05/dynamically-creating-viewscontrollers.html Essentiellement, il implique une nouvelle classe j'appelle le classConstructor, qui prend un nom de classe, le nom de la méthode d'initialisation, et séparées par des virgules arguments. Lorsque vous avez besoin de créer une instance de cette classe, utilisez simplement votre [myClassConstructor create];