2010-08-04 4 views
5

j'ai un protocole Objective-C:redéclarant/Extension typedef défini dans le protocole Objective-C dans la classe conforme au protocole

typedef enum { 
    ViewStateNone 
} ViewState; 

@protocol ViewStateable 

- (void)initViewState:(ViewState)viewState; 
- (void)setViewState:(ViewState)viewState; 

@end 

J'utilisant ce protocole dans la classe suivante:

#import "ViewStateable.h" 

typedef enum { 
    ViewStateNone, 
    ViewStateSummary, 
    ViewStateContact, 
    ViewStateLocation 
} ViewState; 

@interface ViewController : UIViewController <ViewStateable> { 

} 

@end 

Je n'irai pas trop loin dans les détails de mon application, mais ce que je fais ici est typedef une énumération dans un protocole afin que les méthodes du protocole puissent prendre une valeur d'entrée de ce type. Je souhaite ensuite redéclarer ou étendre ce typedef dans les classes conformes à ce protocole, afin que chaque classe puisse avoir ses propres états d'affichage. Cependant, je suis en cours d'exécution dans les deux erreurs suivantes:

  1. Redeclaration of enumerator 'ViewStateNone'
  2. Conflicting types for 'ViewState'

J'ai honte d'admettre que ma connaissance de C (à savoir typedef s) n'est pas exhaustive, si est ce que j'essaie de faire ici, d'une part, possible et, d'autre part, sensible?

Acclamations d'amis.

Répondre

6

Ce n'est pas possible ni sensible. Cela vient du fait que typedefs et enums sont fondamentalement définit juste. (Eh bien, pas vraiment, mais dans ce but, ils le sont.) Si vous avez besoin de faire des choses comme ça, vous voudrez peut-être revoir votre conception (voir ci-dessous).


Plus d'info

typedef type newtype; 

est (presque) équivalente à

#define newtype type; 

et

enum { 
    ViewStateNone 
}; 

est essentiellement le même que

#define ViewStateNone 1 

Il y a quelques subtilités withe ce qui concerne les différences entre les deux, et l'argument le plus convaincant pour l'utilisation énumérations et typedefs est bien sûr la compilation vérification des constantes entières.

Cependant; une fois qu'un typedef enum {} type; a été vu, il ne peut pas être invisible, et une fois qu'il a été vu, son nom lui est réservé, et lui seul.

Il y a des façons de contourner tout cela; mais ce sont des chemins rarement parcourus, et généralement pour de bonnes raisons. Il devient rapidement incroyablement ingérable.

En tant que solution, vous pouvez créer une nouvelle classe, MyViewState, qui représente un état d'affichage et des informations associées, ce qui peut facilement être un wrapper autour d'un NSInteger.


En guise de conclusion: Examinez votre design. Je crains que vous fassiez quelque chose de trop alambiqué.

+0

Merci pour une réponse très claire et réfléchie Williham. Fondamentalement, j'ai x nombre de vues, avec x nombre d'états, tout étant géré par un contrôleur central. En faisant abstraction du changement d'état, j'espérais initialiser et basculer de nombreux états de vue vers l'extérieur avec un seul appel de méthode. Si la technique ci-dessus était possible, je pense qu'elle aurait probablement été remarquablement simple. Hélas, je vais reconsidérer mon design. Merci encore. –

1

Ce n'est certainement pas possible dans la forme que vous l'avez, pour des raisons que les erreurs expliquer assez succinctement. Une constante enum ne peut être déclarée qu'une seule fois dans n'importe quelle portée, et de même un typedef.

De plus, il y a un peu de difficulté conceptuelle à définir un de type dans un protocole que les implémenteurs peuvent ensuite redéfinir. Les implémenteurs doivent être conformes au type, sans y ajouter. Si la classe doit être capable de déterminer son propre ensemble de valeurs, le protocole doit utiliser un type assez général pour contenir tous ceux qui pourraient être voulus. Dans ce cas, vous pouvez utiliser int ou, probablement plus judicieusement, quelque chose de lisible comme NSString. Vous pouvez également ajouter au protocole une autre méthode qui rendra compte des valeurs prises en charge par la classe d'implémentation.

Questions connexes