문제

유형 속성을 엔티티에 할당 할 수 있도록 핵심 데이터 엔티티를 열거 값에 바인딩하는 가장 좋은 방법은 무엇입니까? 다시 말해, 나는 단체가 호출 된 엔티티가 있습니다 Item 와 함께 itemType 내가 열거하고 싶은 재산, 이것에 대한 가장 좋은 방법은 무엇입니까?

도움이 되었습니까?

해결책

값을 열거로 제한하려면 사용자 정의 액세서를 만들어야합니다. 따라서 먼저 열거를 선언합니다.

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

그런 다음 귀하의 재산에 대한 Getters와 Setters를 선언하십시오. 표준 액세서가 스칼라 유형이 아닌 Nsnumber 객체를 기대하고 바인딩이나 KVO 시스템의 어떤 것이 값을 시도하고 액세스하면 문제가 발생하기 때문에 기존 제품을 무시하는 것은 나쁜 생각입니다.

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

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

마지막으로 구현해야합니다 + keyPathsForValuesAffecting<Key> 따라서 ItemType가 변경 될 때 ItemTyperaw에 대한 KVO 알림이 표시됩니다.

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

다른 팁

이 방법을 더 간단하게 할 수 있습니다.

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

@property (nonatomic) Types_t itemType;

그리고 당신의 모델에서 설정하십시오 itemType 16 비트 숫자입니다. 모두 완료되었습니다. 추가 코드가 필요하지 않습니다. 평소에 넣으십시오

@dynamic itemType;

Xcode를 사용하여 생성하는 경우 NSManagedObject 서브 클래스, "기본 데이터 유형에 스칼라 속성을 사용하십시오"설정이 확인됩니다.

내가 고려하고있는 대안적인 접근법은 열거를 전혀 선언하는 것이 아니라 NSNumber의 범주 방법으로 값을 선언하는 것입니다.

Mogenerator를 사용하는 경우 다음을 살펴보십시오. https://github.com/rentzsch/mogenerator/wiki/using-enums-as-types. 정수 16 속성을 호출 할 수 있습니다 itemType, a attributeValueScalarType 가치 Item 사용자 정보에서. 그런 다음 엔티티의 사용자 정보에서 additionalHeaderFileName 헤더의 이름으로 Item Enum은 정의됩니다. 헤더 파일을 생성 할 때 Mogenerator는 자동으로 속성에 Item 유형.

속성 유형을 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

열거는 표준 쇼트로 뒷받침되므로 nsnumber 래퍼를 사용할 수없고 속성을 스칼라 값으로 직접 설정할 수도 있습니다. 핵심 데이터 모델의 데이터 유형을 "Integer 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];

아래에 붙여진 코드는 저를 위해 작동하며 전체 작업 예로 추가했습니다. 이 접근법에 대한 의견을 듣고 싶습니다. 앱 전체에서 광범위하게 사용하려고합니다.

  • 나는 @dynamic을 제자리에 두었습니다.

  • Ikenndac의 답변에 따라 기본 getter/setter 이름을 무시하지 않았습니다.

  • TypEdef 유효한 값에 대한 NSAssert를 통해 범위 점검을 포함 시켰습니다.

  • 주어진 typedef에 대한 문자열 값을 얻는 메소드도 추가했습니다.

  • 나는 "k"보다는 "c"로 상수를 접두사합니다. "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

나는 이것을 많이하고 다음 양식을 유용하다고 생각합니다.

// 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"
}

그리고 그것을 pedantic이라고 부르지 만, 나는 다음과 같은 필드 이름에 열거를 사용합니다.

public enum Field:String {

    case Account = "account"
}

이것은 복잡한 데이터 모델에 힘들 수 있기 때문에 엄마 / 엔티티를 소비하여 모든 매핑을 뱉어내는 코드 생성기를 썼습니다. 내 입력은 테이블/행에서 열거 형식으로 사전이됩니다. 내가 그곳에있는 동안, 나는 또한 JSON 직렬화 코드를 생성했습니다. 나는 매우 복잡한 모델을 위해 이것을 해냈고 그것은 큰 시간 절약으로 판명되었습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top