답변:
값을 열거 형으로 제한하려면 사용자 지정 접근자를 만들어야합니다. 따라서 먼저 다음과 같이 열거 형을 선언합니다.
typedef enum {
kPaymentFrequencyOneOff = 0,
kPaymentFrequencyYearly = 1,
kPaymentFrequencyMonthly = 2,
kPaymentFrequencyWeekly = 3
} PaymentFrequency;
그런 다음 속성에 대한 getter 및 setter를 선언하십시오. 표준 접근자가 스칼라 유형이 아닌 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"];
}
int16_t
됩니다.
이 방법으로 더 간단하게 할 수 있습니다.
typedef enum Types_e : int16_t {
TypeA = 0,
TypeB = 1,
} Types_t;
@property (nonatomic) Types_t itemType;
그리고 모델에서 itemType
16 비트 숫자로 설정 합니다. 모두 완료되었습니다. 추가 코드가 필요하지 않습니다. 평소대로 넣어
@dynamic itemType;
Xcode를 사용하여 NSManagedObject
하위 클래스를 만드는 경우 " 기본 데이터 유형에 스칼라 속성 사용 "설정이 선택되어 있는지 확인하십시오.
retain
메모리 관리와 관련이 있습니다.
내가 고려하고있는 다른 접근 방식은 열거 형을 전혀 선언하지 않고 대신 NSNumber의 범주 메서드로 값을 선언하는 것입니다.
mogenerator를 사용하는 경우 https://github.com/rentzsch/mogenerator/wiki/Using-enums-as-types를 살펴보십시오 . 당신은라는 정수 (16) 속성을 가질 수 itemType
A를, attributeValueScalarType
의 값 Item
은 사용자 정보에 있습니다. 그런 다음 엔터티의 사용자 정보 additionalHeaderFileName
에서 Item
열거 형이 정의 된 헤더의 이름으로 설정 합니다 . 헤더 파일을 생성 할 때 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
열거 형은 표준 short로 뒷받침되기 때문에 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];
이 작업을 많이 수행했으며 다음 양식이 유용하다는 것을 알았습니다.
// 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 / 엔티티를 사용하는 코드 생성기를 작성했습니다. 내 입력은 Table / Row에서 Enum 유형으로의 사전이됩니다. 거기에있는 동안 JSON 직렬화 코드도 생성했습니다. 매우 복잡한 모델에 대해이 작업을 수행했으며 시간을 크게 절약 할 수있었습니다.
아래에 붙여 넣은 코드가 저에게 효과적이며 전체 작업 예제로 추가했습니다. 이 접근 방식을 앱 전체에서 광범위하게 사용할 계획이므로이 접근 방식에 대한 의견을 듣고 싶습니다.
@dynamic은 속성에 명명 된 getter / setter가 만족하므로 그대로 두었습니다.
iKenndac의 답변에 따라 기본 getter / setter 이름을 재정의하지 않았습니다.
typedef 유효한 값에 대해 NSAssert를 통해 일부 범위 검사를 포함했습니다.
또한 주어진 typedef에 대한 문자열 값을 얻는 방법을 추가했습니다.
상수 앞에 "k"가 아닌 "c"를 붙입니다. 나는 "k"(수학의 기원, 역사)에 대한 이유를 알고 있지만, ESL 코드를 읽는 것처럼 느껴져서 "c"를 사용합니다. 개인적인 일입니다.
비슷한 질문이 있습니다. typedef as a Core data type
이 접근 방식에 대한 의견을 보내 주시면 감사하겠습니다.
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
"YourClass"라는 엔티티를 생성하는 경우 Xcode는 "Data Model Inspector"에서 기본 Codegen 유형으로 "Class Definition"을 자동으로 선택합니다. 그러면 아래와 같은 클래스가 생성됩니다.
// YourClass+CoreDataClass.swift
@objc(YourClass)
public class YourClass: NSManagedObject {
}
// YourClass+CoreDataClass.h
@interface YourClass : NSManagedObject
@end
#import "YourClass+CoreDataProperties.h"
// YourClass+CoreDataClass.m
#import "YourClass+CoreDataClass.h"
@implementation YourClass
@end
Xcode의 "Class Definition"대신 Codegen 옵션에서 "Category / Extension"을 선택합니다.
이제 열거 형을 추가하려면 자동 생성 클래스에 대한 다른 확장을 만들고 여기에 열거 형 정의를 아래와 같이 추가합니다.
// YourClass+Extension.h
#import "YourClass+CoreDataClass.h" // That was the trick for me!
@interface YourClass (Extension)
@end
// YourClass+Extension.m
#import "YourClass+Extension.h"
@implementation YourClass (Extension)
typedef NS_ENUM(int16_t, YourEnumType) {
YourEnumTypeStarted,
YourEnumTypeDone,
YourEnumTypePaused,
YourEnumTypeInternetConnectionError,
YourEnumTypeFailed
};
@end
이제 값을 열거 형으로 제한하려는 경우 사용자 지정 접근자를 만들 수 있습니다. 질문 소유자가 수락 한 답변을 확인하십시오 . 또는 아래와 같이 캐스트 연산자를 사용하여 명시 적으로 변환 방법으로 설정하는 동안 열거 형을 변환 할 수 있습니다.
model.yourEnumProperty = (int16_t)YourEnumTypeStarted;
Xcode는 이제 모델링 도구에서 NSManagedObject 하위 클래스의 자동 생성을 지원합니다. 엔티티 검사기에서 :
수동 / 없음이 기본값이며 이전 동작입니다. 이 경우 자체 서브 클래스를 구현하거나 NSManagedObject를 사용해야합니다. 범주 / 확장자는 ClassName + CoreDataGeneratedProperties와 같은 이름의 파일에 클래스 확장을 생성합니다. 메인 클래스를 선언 / 구현해야합니다 (Obj-C에서 헤더를 통해 확장은 ClassName.h라는 이름을 가져올 수 있음). Class Definition은 ClassName + CoreDataClass와 같은 이름의 하위 클래스 파일과 Category / Extension에 대해 생성 된 파일을 생성합니다. 생성 된 파일은 DerivedData에 배치되고 모델이 저장된 후 첫 번째 빌드에서 다시 빌드됩니다. 또한 Xcode에 의해 색인화되므로 참조를 명령 클릭하고 파일 이름으로 빠르게 열기가 작동합니다.
enum
s가 아니죠 ?