实现与核心数据枚举的最佳方式(Best way to implement Enums with Co

2019-09-01 05:54发布

什么是绑定核心数据实体,从而使我能够指定一个类型属性的实体枚举值的最佳方法? 换句话说,我有一个名为实体ItemitemType ,我想绑定到一个枚举属性,什么是要对这个的最佳方式。

Answer 1:

你必须创建自定义的访问者,如果你想要将其值限制在一个枚举。 所以,首先你宣布一个枚举,如下所示:

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

然后,声明getter和setter你的财产。 这是一个坏主意,覆盖现有的,因为标准存取期待一个NSNumber对象,而不是标量类型,你会遇到麻烦,如果在绑定或志愿系统任何试图访问你的价值。

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

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

最后,你应该实现+ keyPathsForValuesAffecting<Key>等你拿志愿通知itemTypeRaw时ITEMTYPE变化。

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


Answer 2:

你可以做到这一点的方式,方法简单:

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

@property (nonatomic) Types_t itemType;

而在你的模型,设置itemType是一个16位的数字。 全部完成。 没有额外的代码需要。 只要把你平常

@dynamic itemType;

如果您使用Xcode中创建你的NSManagedObject子类,确保“ 用标属性基本数据类型 ”设置检查。



Answer 3:

我正在考虑另一种方法是不申报枚举所有,但,而不是申报值上的NSNumber类的方法。



Answer 4:

如果您使用mogenerator,看看这个: https://github.com/rentzsch/mogenerator/wiki/Using-enums-as-types 。 你可以有一个整数16的属性称为itemType ,具有attributeValueScalarType的值Item的用户信息。 然后,在你的实体的用户信息,设置additionalHeaderFileName到了头名Item枚举中定义。当生成你的头文件,mogenerator将自动进行物业有Item类型。



Answer 5:

我设置的属性类型,16位整数,然后用这个:

#import <CoreData/CoreData.h>

enum {
    LDDirtyTypeRecord = 0,
    LDDirtyTypeAttachment
};
typedef int16_t LDDirtyType;

enum {
    LDDirtyActionInsert = 0,
    LDDirtyActionDelete
};
typedef int16_t LDDirtyAction;


@interface LDDirty : NSManagedObject

@property (nonatomic, strong) NSString* identifier;
@property (nonatomic) LDDirtyType type;
@property (nonatomic) LDDirtyAction action;

@end

...

#import "LDDirty.h"

@implementation LDDirty

@dynamic identifier;
@dynamic type;
@dynamic action;

@end


Answer 6:

由于枚举由一个标准的短期支持,你也可以不使用NSNumber的包装并直接设置属性为标量值。 确保设置在核心数据模型的数据类型为“整型32”。

MyEntity.h

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

@interface myEntity : NSManagedObject

@property (nonatomic) int32_t coreDataEnumStorage;

在其他地方的代码

myEntityInstance.coreDataEnumStorage = kEnumThing;

或者从JSON字符串解析或从文件加载

myEntityInstance.coreDataEnumStorage = [myStringOfAnInteger intValue];


Answer 7:

粘贴下面的代码对我的作品,我已经添加了它作为完整的工作示例。 我想听听你对这种做法的意见,因为我计划广泛地使用它在我的应用程序。

  • 我留在原地的@dynamic,因为它是由然后在属性命名的getter / setter满足。

  • 按照由iKenndac答案,我还没有覆盖默认的getter / setter的名字。

  • 我将在typedef的有效值通过NSAssert一些范围检查。

  • 我还添加了一个方法来获取给定的typedef的字符串值。

  • 我前面加上“C”,而不是“K”的常量。 我知道后面的“K”(数学的起源,历史)的理由,但感觉像我读ESL代码,所以我用“C”。 只是个人的事情。

还有一个类似的问题在这里: 的typedef作为核心数据类型

我会很感激这种方法的任何输入。

Word.h

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>

typedef enum {
    cPresent            = 0,    
    cFuturProche        = 1,    
    cPasseCompose       = 2,    
    cImparfait          = 3,    
    cFuturSimple        = 4,    
    cImperatif          = 5     
} TenseTypeEnum;

@class Word;
@interface Word : NSManagedObject

@property (nonatomic, retain) NSString * word;
@property (nonatomic, getter = tenseRaw, setter = setTenseRaw:) TenseTypeEnum tense;

// custom getter & setter methods
-(void)setTenseRaw:(TenseTypeEnum)newValue;
-(TenseTypeEnum)tenseRaw;
- (NSString *)textForTenseType:(TenseTypeEnum)tenseType;

@end


Word.m


#import "Word.h"

@implementation Word

@dynamic word;
@dynamic tense;

// custom getter & setter methods
-(void)setTenseRaw:(TenseTypeEnum)newValue
{
    NSNumber *numberValue = [NSNumber numberWithInt:newValue];
    [self willChangeValueForKey:@"tense"];
    [self setPrimitiveValue:numberValue forKey:@"tense"];
    [self didChangeValueForKey:@"tense"];
}


-(TenseTypeEnum)tenseRaw
{
    [self willAccessValueForKey:@"tense"];
    NSNumber *numberValue = [self primitiveValueForKey:@"tense"];
    [self didAccessValueForKey:@"tense"];
    int intValue = [numberValue intValue];

    NSAssert(intValue >= 0 && intValue <= 5, @"unsupported tense type");
    return (TenseTypeEnum) intValue;
}


- (NSString *)textForTenseType:(TenseTypeEnum)tenseType
{
    NSString *tenseText = [[NSString alloc] init];

    switch(tenseType){
        case cPresent:
            tenseText = @"présent";
            break;
        case cFuturProche:
            tenseText = @"futur proche";
            break;
        case cPasseCompose:
            tenseText = @"passé composé";
            break;
        case cImparfait:
            tenseText = @"imparfait";
            break;
        case cFuturSimple:
            tenseText = @"futur simple";
            break;
        case cImperatif:
            tenseText = @"impératif";
            break;
    }
    return tenseText;
}


@end


Answer 8:

我这样做了很多,找到下面的表格是有用的:

// accountType
public var account:AccountType {
    get {
        willAccessValueForKey(Field.Account.rawValue)
        defer { didAccessValueForKey(Field.Account.rawValue) }
        return primitiveAccountType.flatMap { AccountType(rawValue: $0) } ?? .New }
    set {
        willChangeValueForKey(Field.Account.rawValue)
        defer { didChangeValueForKey(Field.Account.rawValue) }
        primitiveAccountType = newValue.rawValue }}
@NSManaged private var primitiveAccountType: String?

在这种情况下,枚举是非常简单的:

public enum AccountType: String {
    case New = "new"
    case Registered = "full"
}

并调用它的迂腐,但我用枚举的字段名,就像这样:

public enum Field:String {

    case Account = "account"
}

由于这样做会变得繁琐复杂的数据模型,我写了一个代码生成器,消耗MOM /实体吐出所有的映射。 我的输入最终被从表字典/行到Enum类型。 当我在这,我也产生了JSON序列码。 我做这个非常复杂的模型,它已被证明是一个很大的节省时间。



文章来源: Best way to implement Enums with Core Data