Как создать класс (ы) для хранения многоуровневых данных? - PullRequest
0 голосов
/ 20 марта 2012

Мне нужно хранить многоуровневые данные для приложения флэш-карты, которое я пишу, и я мог бы использовать некоторую помощь в выяснении 1) Как управлять данными и 2) Как их хранить.

Данные разбиты следующим образом: а) карта содержит 2 строки б) Пакет содержит строку "PackName" и массив карт c) Deck содержит строку "DeckName" и массив пакетов

Сейчас у меня есть 3 класса: карта, колода, колода.

//Card.h
@interface Card : NSObject {
    NSString        *primaryPhrase;
    NSString        *secondaryPhrase;
}
@property (nonatomic,retain)NSString        *primaryPhrase;
@property (nonatomic,retain)NSString        *secondaryPhrase;
@end


Card.m
@implementation Card
@synthesize primaryPhrase;
@synthesize secondaryPhrase;
-(id)init{
    if(self=[super init]){
    }
    return self;
}
@end

Pack.h
@interface Pack : NSObject{
    NSString        *packName;
    NSMutableArray  *cards; //array of card classes
    BOOL            isInUse;
}
@property (nonatomic,retain)NSMutableArray  *cards;
@property (nonatomic,retain)NSString        *packName;
@property (nonatomic,assign)BOOL            isInUse;
@end

Pack.m
@implementation Pack
@synthesize packName;
@synthesize cards;
@synthesize isInUse;
-(id)init{
    if(self=[super init]){
        self.isInUse=YES;
    }
    return self;
}
@end

Deck.h
@interface Deck : NSObject <NSCoding>{
    NSString        *deckName;
    NSMutableArray  *packs; //array of pack classes
    NSString        *primaryLang;
    NSString        *secondaryLang;
}
@property (nonatomic,retain)NSMutableArray  *packs;
@property (nonatomic,retain)NSString        *deckName;
@property (nonatomic,retain)NSString        *primaryLang;
@property (nonatomic,retain)NSString        *secondaryLang;

- (void) encodeWithCoder:(NSCoder*)encoder;
- (id) initWithCoder:(NSCoder*)decoder;
@end

Deck.m
#import "Deck.h"
@implementation Deck
@synthesize packs;
@synthesize deckName;
@synthesize primaryLang;
@synthesize secondaryLang;

//Default settings for each new Deck
-(id)init{
    if(self=[super init]){
    }
    return self;
}
-(void)encodeWithCoder:(NSCoder*)encoder{
    [encoder encodeObject:packs forKey:@"packs"];
    [encoder encodeObject:deckName forKey:@"deckName"];
    [encoder encodeObject:primaryLang forKey:@"primaryLang"];
    [encoder encodeObject:secondaryLang forKey:@"secondaryLang"];
}
-(id)initWithCoder:(NSCoder*)decoder{
    if(self=[super init]){
        packs=[decoder decodeObjectForKey:@"packs"];
        deckName=[decoder decodeObjectForKey:@"deckName"];
        primaryLang=[decoder decodeObjectForKey:@"primaryLang"];
        secondaryLang=[decoder decodeObjectForKey:@"secondaryLang"];
    }
    return self;
}
@end

Затем я использую NSMutableArray «allDecks» для хранения колод, которые, в свою очередь, содержат карты, но я даже не смог заставить это работать (никаких ошибок, но «имя пакета» всегда пусто):

    for(int i=0; i<=2; i++){
        Deck *newdeck=[[Deck alloc]init];
        [globDat.allDecks addObject:newdeck];
    }
    ((Deck *)[globDat.allDecks objectAtIndex:0]).deckName=@"DeckName 0";
    ((Deck *)[globDat.allDecks objectAtIndex:1]).deckName=@"DeckName 1";
    ((Deck *)[globDat.allDecks objectAtIndex:2]).deckName=@"DeckName 2";
    for(int i=0; i<=2; i++){
        Pack *newpack=[[Pack alloc] init];
        [((Deck *)[globDat.allDecks objectAtIndex:i]).packs addObject:newpack];
    }
    for(int j=0; j<+2; j++){
        ((Pack *)[((Deck *)[globDat.allDecks objectAtIndex:0]).packs objectAtIndex:j]).packName=@"pack name";
    }

    NSLog(@"*** NIL sample pack name=%@",((Pack *)[((Deck *)[globDat.allDecks objectAtIndex:0]).packs objectAtIndex:0]).packName);
 //always returns null

Работать со структурой довольно громоздко. Это лучший способ управлять этими данными?

Кроме того, кодировка, похоже, не сохраняет встроенные массивы (Pack и Card).

Ответы [ 2 ]

1 голос
/ 20 марта 2012

Честно говоря, я бы продолжил, как вы делаете вещи.Причина того, что Pack и Card не сохраняются, заключается в том, что каждый из них должен реализовать методы encodeWithCoder: и initWithCoder:.

Card.h

@interface Card : NSObject

@property (nonatomic,retain)NSString *primaryPhrase;
@property (nonatomic,retain)NSString *secondaryPhrase;

@end

Card.m

@implementation Card

@synthesize primaryPhrase, secondaryPhrase;

-(id)init{
    if(self=[super init]){
    }
    return self;
}

-(void)encodeWithCoder:(NSCoder*)encoder{
    [encoder encodeObject:primaryPhrase forKey:@"primaryPhrase"];
    [encoder encodeObject:secondaryPhrase forKey:@"secondaryPhrase"];
}

-(id)initWithCoder:(NSCoder*)decoder{
    if(self=[super init]){
        primaryPhrase=[decoder decodeObjectForKey:@"primaryPhrase"];
        secondaryPhrase=[decoder decodeObjectForKey:@"secondaryPhrase"];
    }
    return self;
}

@end

Pack.h

@interface Pack : NSObject

@property (nonatomic,retain)NSMutableArray  *cards;
@property (nonatomic,retain)NSString        *packName;
@property (nonatomic,assign)BOOL            isInUse;

@end

Pack.m

@implementation Pack

@synthesize packName, cards, isInUse;

-(id)init{
    if(self=[super init]){
        self.isInUse=YES;
    }
    return self;
}

-(void)encodeWithCoder:(NSCoder*)encoder{
    [encoder encodeObject:packName forKey:@"packName"];
    [encoder encodeObject:cards forKey:@"cards"];
    [encoder encodeObject:[NSNumber numberWithBool:isInUse] forKey:@"isInuse"];
}

-(id)initWithCoder:(NSCoder*)decoder{
    if(self=[super init]){
        packName=[decoder decodeObjectForKey:@"packName"];
        cards=[decoder decodeObjectForKey:@"cards"];
        isInUse=[[decoder decodeObjectForKey:@"isInUse"] boolValue];
    }
    return self;
}

@end

Deck.h

@interface Deck : NSObject <NSCoding>

@property (nonatomic,retain)NSMutableArray  *packs;
@property (nonatomic,retain)NSString        *deckName;
@property (nonatomic,retain)NSString        *primaryLang;
@property (nonatomic,retain)NSString        *secondaryLang;

@end

Палуба.м

#import "Deck.h"
@implementation Deck

@synthesize packs, deckName, primaryLang, secondaryLang;

-(id)init{
    if(self=[super init]){
    }
    return self;
}

-(void)encodeWithCoder:(NSCoder*)encoder{
    [encoder encodeObject:packs forKey:@"packs"];
    [encoder encodeObject:deckName forKey:@"deckName"];
    [encoder encodeObject:primaryLang forKey:@"primaryLang"];
    [encoder encodeObject:secondaryLang forKey:@"secondaryLang"];
}

-(id)initWithCoder:(NSCoder*)decoder{
    if(self=[super init]){
        packs=[decoder decodeObjectForKey:@"packs"];
        deckName=[decoder decodeObjectForKey:@"deckName"];
        primaryLang=[decoder decodeObjectForKey:@"primaryLang"];
        secondaryLang=[decoder decodeObjectForKey:@"secondaryLang"];
    }
    return self;
}
1 голос
/ 20 марта 2012

Я опубликую это как ответ, хотя это действительно мнение.

Я бы использовал Базовые данные для слоя модели.Вам не нужно заниматься сериализацией графа объектов, как сейчас.Скорее, постоянство графов объектов в основном обрабатывается платформой.Существует кривая обучения - для Apple, это не «технология начального уровня», но она будет намного более управляемой в долгосрочной перспективе.

Что касается проблемы с сериализацией массивов в вашем объектеграфик, NSMutableArray соответствует протоколу NSCoding;есть другая проблема.Вместо:

packs=[decoder decodeObjectForKey:@"packs"];

Вы не имеете в виду:

self.packs = [decoder decodeObjectForKey:@"packs"];

или

packs = [[decoder decodeObjectForKey:@"packs"] retain];

(я предполагаю, что вы не используете ARC ...)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...