110 votes

Meilleure façon d'implémenter les Enums avec Core Data

Quelle est la meilleure façon de lier des entités Core Data à des valeurs d'énumération afin de pouvoir attribuer une propriété de type à l'entité ? En d'autres termes, j'ai une entité appelée Item avec un itemType que je veux lier à un enum, quelle est la meilleure façon de procéder ?

131voto

iKenndac Points 14855

Vous devrez créer des accesseurs personnalisés si vous souhaitez restreindre les valeurs d'un enum. Donc, tout d'abord, vous devez déclarer un enum, comme ceci :

typedef enum {
    kPaymentFrequencyOneOff = 0,
    kPaymentFrequencyYearly = 1,
    kPaymentFrequencyMonthly = 2,
    kPaymentFrequencyWeekly = 3
} PaymentFrequency;

Ensuite, déclarez les getters et setters pour votre propriété. C'est une mauvaise idée de remplacer ceux qui existent déjà, car les accesseurs standard attendent un objet NSNumber plutôt qu'un type scalaire, et vous aurez des problèmes si quelque chose dans les bindings ou les systèmes KVO essaie d'accéder à votre valeur.

- (PaymentFrequency)itemTypeRaw {
    return (PaymentFrequency)[[self itemType] intValue];
}

- (void)setItemTypeRaw:(PaymentFrequency)type {
    [self setItemType:[NSNumber numberWithInt:type]];
}

Enfin, vous devez mettre en œuvre + keyPathsForValuesAffecting<Key> afin que vous receviez des notifications KVO pour itemTypeRaw lorsque itemType change.

+ (NSSet *)keyPathsForValuesAffectingItemTypeRaw {
    return [NSSet setWithObject:@"itemType"];
}

2 votes

Merci - dommage que Core Data ne supporte pas cela nativement. Je veux dire : Xcode génère des fichiers de classe, pourquoi pas enum s ?

0 votes

Le dernier code est celui qui permet d'observer item itemTypeRaw. Cependant, vous pouvez simplement observer item itemType au lieu de itemTypeRaw, n'est-ce pas ?

2 votes

Avec Xcode 4.5, vous n'avez pas besoin de tout cela. Jetez un coup d'oeil à ma réponse. Vous avez juste besoin de définir l'enum en tant que int16_t et vous êtes prêt.

80voto

Daniel Eggert Points 4042

Vous pouvez faire ça de manière beaucoup plus simple :

typedef enum Types_e : int16_t {
    TypeA = 0,
    TypeB = 1,
} Types_t;

@property (nonatomic) Types_t itemType;

Et dans votre modèle, mettez itemType pour être un nombre de 16 bits. Tout est fait. Aucun code supplémentaire n'est nécessaire. Il suffit de mettre votre habituel

@dynamic itemType;

Si vous utilisez Xcode pour créer votre NSManagedObject assurez-vous que l'élément " utiliser des propriétés scalaires pour les types de données primitifs Le paramètre " " est vérifié.

0 votes

Y a-t-il des limites aux versions d'iOS / OS X avec lesquelles cela fonctionnera ?

0 votes

Cela a fonctionné aussi longtemps que je m'en souvienne, mais je ne peux rien promettre. Je me souviens l'avoir utilisé sur iOS 5, mais je ne sais pas pourquoi il ne fonctionnerait pas avec iOS 4...

0 votes

Notez qu'il s'agit d'une fonctionnalité de C++11 appelée "classes enum". cprogramming.com/c++11/

22voto

Mike Abdullah Points 9464

Une autre approche que j'envisage est de ne pas déclarer d'enum du tout, mais de déclarer les valeurs comme des méthodes de catégorie sur NSNumber.

0 votes

Intéressant. Cela semble définitivement faisable.

0 votes

Une idée brillante ! tellement plus facile que de créer des tables dans la base de données, à moins que votre base de données soit remplie à partir d'un service web, il est probablement préférable d'utiliser une table de base de données !

6 votes

5voto

jfla Points 80

Si vous utilisez mogenerator, jetez un coup d'œil à ceci : https://github.com/rentzsch/mogenerator/wiki/Using-enums-as-types . Vous pouvez avoir un attribut Integer 16 appelé itemType avec un attributeValueScalarType valeur de Item dans les informations sur l'utilisateur. Ensuite, dans les informations sur l'utilisateur de votre entité, définissez les éléments suivants additionalHeaderFileName au nom de l'en-tête que le Item L'enum est défini dans. Lors de la génération de vos fichiers d'en-tête, mogenerator fera automatiquement en sorte que la propriété ait l'attribut Item type.

1voto

puppybits Points 682

Étant donné que les enums sont soutenus par un court standard, vous pourriez également ne pas utiliser le wrapper NSNumber et définir la propriété directement comme une valeur scalaire. Veillez à définir le type de données dans le modèle de données de base comme "Integer 32".

MyEntity.h

typedef enum {
kEnumThing, /* 0 is implied */
kEnumWidget, /* 1 is implied */
} MyThingAMaBobs;

@interface myEntity : NSManagedObject

@property (nonatomic) int32_t coreDataEnumStorage;

Ailleurs dans le code

myEntityInstance.coreDataEnumStorage = kEnumThing;

Ou l'analyse d'une chaîne JSON ou le chargement d'un fichier.

myEntityInstance.coreDataEnumStorage = [myStringOfAnInteger intValue];

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X