iphone - أفضل طريقة لتنفيذ 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"];
}

ما هي أفضل طريقة لربط كيانات البيانات الأساسية بقيم التعداد بحيث يمكنني تعيين خاصية نوع للكيان؟ وبعبارة أخرى ، لدي كيان يسمى 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 في المكان ، حيث أنه راض بعد ذلك عن طريق getter / setter المسمى في الخاصية.

  • وفقا للإجابة عن طريق iKenndac ، لم أكن تجاوزت أسماء getter / setter الافتراضية.

  • لقد قمت بتضمين بعض التحقق من النطاق عبر NSAssert على القيم الصالحة لـ typedef.

  • لقد قمت أيضًا بإضافة طريقة للحصول على قيمة سلسلة لـ 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



Related