iphone книги cocoa - Лучший способ реализации Enums с базовыми данными




4 Answers

Вам нужно будет создать пользовательские аксессоры, если вы хотите ограничить значения перечислением. Итак, сначала вы объявите перечисление, например:

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

Затем объявите получателей и сеттеров для вашего имущества. Плохая идея переопределить существующие, поскольку стандартные аксессоры ожидают объект NSNumber, а не скалярный тип, и у вас возникнут проблемы, если что-либо в привязках или системах KVO попытается получить доступ к вашему значению.

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

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

Наконец, вы должны реализовать + keyPathsForValuesAffecting<Key> чтобы вы получали KVO-уведомления для itemTypeRaw, когда itemType изменяется.

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

Каков наилучший способ привязать объекты Core Data к значениям перечисления, чтобы я мог назначить свойство типа для объекта? Другими словами, у меня есть объект под названием Item с свойством itemType который я хочу itemType к перечислению, что лучше всего подходит для этого.




Альтернативный подход, который я рассматриваю, - это не объявлять перечисление вообще, а вместо этого объявлять значения как методы категорий в NSNumber.




Я установил тип атрибута как 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



Код, вставленный ниже, работает для меня, и я добавил его как полный рабочий пример. Я хотел бы услышать мнения по этому подходу, поскольку я планирую широко использовать его в своих приложениях.

  • Я оставил @dynamic на месте, так как тогда он удовлетворен получателем / установщиком, указанным в свойстве.

  • В соответствии с ответом iKenndac, я не переопределял имена получателей / установщиков по умолчанию.

  • Я включил некоторую проверку диапазона через NSAssert по допустимым значениям typedef.

  • Я также добавил метод получения строкового значения для данного typedef.

  • Я префиксные константы с «c», а не «k». Я знаю аргументы за «k» (математическое происхождение, историческое), но мне кажется, что я читаю с ним код ESL, поэтому я использую «c». Просто личное дело.

Здесь есть аналогичный вопрос: typedef как тип данных Core

Я был бы признателен за любой вклад в этот подход.

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



Related