أفضل طريقة لتنفيذ التعدادات باستخدام البيانات الأساسية

StackOverflow https://stackoverflow.com/questions/1624297

سؤال

ما هي أفضل طريقة لربط كيانات البيانات الأساسية بقيم التعداد حتى أتمكن من تعيين خاصية النوع للكيان؟وبعبارة أخرى، لدي كيان يسمى Item مع ال itemType الخاصية التي أرغب في ربطها بالتعداد، ما هي أفضل طريقة للقيام بذلك.

هل كانت مفيدة؟

المحلول

وسيكون لديك لإنشاء يمكنهم الدخول مخصص إذا كنت ترغب في تقييد القيم إلى التعداد. لذلك، أولا كنت تعلن عن التعداد، كما يلي:

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

وبعد ذلك، أعلن حاصل على واضعي عن الممتلكات الخاصة بك. انها فكرة سيئة لتجاوز تلك القائمة، منذ يمكنهم الدخول القياسية تتوقع كائن 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"];
}

نصائح أخرى

ويمكنك القيام بهذه الطريقة، طريقة أكثر بساطة:

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

@property (nonatomic) Types_t itemType;

وفي النموذج الخاص بك، تعيين itemType أن يكون عدد 16-بت. كله تمام. أي رمز إضافي حاجة. وضعت للتو في المعتاد الخاص بك

@dynamic itemType;

إذا كنت تستخدم كسكودي لخلق فئة فرعية NSManagedObject الخاص بك، تأكد من أن "<م> استخدام الخصائص العددية لأنواع البيانات البدائية " محددا الإعداد.

وثمة نهج بديل أنا النظر هو عدم الإعلان عن التعداد في كل شيء، ولكن بدلا من ذلك أعلن القيم كما أساليب الفئة على NSNumber.

إذا كنت تستخدم mogenerator، إلقاء نظرة على هذا: الشبكي : //github.com/rentzsch/mogenerator/wiki/Using-enums-as-types . هل يمكن أن يكون عدد صحيح 16 سمة تسمى itemType، بقيمة 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

ومنذ وتدعم تتضمن التعدادات التي كتبها قصيرة القياسي الذي يمكن أيضا أن عدم استخدام المجمع 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];

الكود الملصق أدناه يناسبني، وقمت بإضافته كمثال عمل كامل.أود أن أسمع آراء حول هذا النهج، حيث أخطط لاستخدامه على نطاق واسع في جميع تطبيقاتي.

  • لقد تركت @dynamic في مكانه، حيث يتم إرضاؤه بعد ذلك بواسطة المُحضر/المُحدد المُسمى في الخاصية.

  • وفقًا لإجابة 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

ولقد فعلت هذا كثيرا، والعثور على النموذج التالي لتكون مفيدة:

// 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 / الكيانات لبصق كل تعيينات. بلدي المدخلات في نهاية الأمر قاموس من الجدول / صف إلى نوع التعداد. بينما كنت في ذلك، وأنا أيضا ولدت JSON رمز التسلسل. لقد فعلت ذلك لنماذج معقدة جدا، وحولتها إلى أن تكون فترة التوقف الكبيرة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top