如何创建用于存储多级数据的类?

时间:2012-03-20 16:49:01

标签: objective-c

我需要存储我正在编写的闪存卡应用程序的多级数据,我可以使用一些帮助搞清楚1)如何管理数据和2)如何存储它。

数据分解如下: a)卡包含2个字符串 b)Pack包含一个String“PackName”和一组Cards c)Deck包含一个字符串“DeckName”和一个Packs数组

现在我有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”来保存Decks,而Decks又包含Cards,但我甚至无法使其工作(没有错误,但“包名”始终为null):

    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

使用这个结构非常麻烦。 这是管理这些数据的最佳方式吗?

另外,编码似乎不会保存嵌入式阵列(包和卡)。

2 个答案:

答案 0 :(得分:1)

我会发布这个作为答案,虽然这真的是一个意见。

我会将Core Data用于模型层。您不需要像现在一样处理对象图的序列化。相反,对象图持久性主要由框架处理。有一个学习曲线 - 每个Apple,它不是一个“入门级技术” - 但从长远来看它将更易于管理。

对于对象图中序列化序列化的问题,NSMutableArray符合NSCoding协议;还有一些问题。而不是:

packs=[decoder decodeObjectForKey:@"packs"];
你不是说:

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

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

(我假设你没有使用ARC ......)

答案 1 :(得分:1)

老实说,我会继续你做事的方式。 PackCard未被保存的原因是因为他们每个人都需要实施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

Deck.m

#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;
}