NSKeyedArchiver的基础用法

代码如下:

NSString *str = @"abc";
NSString *astr = @"efg";
NSArray *Array = [NSArray arrayWithObjects:str, astr, nil];
     
//保存数据
NSString *Path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; NSString *filename = [Path stringByAppendingPathComponent:@"test.plist"];
[NSKeyedArchiver archiveRootObject:Array toFile:filename];
     
str = @"a";
astr = @"";
     
//加载数据
NSArray *arr = [NSKeyedUnarchiver unarchiveObjectWithFile: filename];
str = [arr objectAtIndex:0];
astr =  [arr objectAtIndex:1];
     
NSLog(@"str:%@",str);
NSLog(@"astr:%@",astr);


 

 

下面是一个数据持久化的应用的实例:

开发应用程序时,有一个很好的机会你会希望有一些持久性排序保存名称,密码,分数等) NSUserDefaults提供了一个简单的方法来安全存储信息然而,你可能需要一个更强大解决方案逻辑数据抽象不应该有符合持久性机制限制你需要一个解决方案,具有足够的灵活性来归档所有你的对象只是字符串数组和字典这就是NSKeyed(Un)Archiver的用武之地。

这里处理我们运动教练创建一个需要为他的运动员统计资料归档/检索解决方案讨论的规格我们已经打破我们抽象

我们有一个ScoreCard 将举行一个运动员的最佳时机所有的分数数组

我们一个Athlete包含运动员的具体信息记分卡实例

我们有Roster包含了一些名册的具体信息运动员实例数组一起

这里是我们简单的类代码

// ScoreCard.h
#import <Foundation/Foundation.h>

@interface ScoreCard : NSObject <NSCoding> {
    
    NSString *bestTime;
    NSMutableArray *allTimes;
    
}

@property (copy) NSString *bestTime;
@property (copy) NSMutableArray *allTimes;

// other methods not relevant to this tutorial go here

@end

@implementation ScoreCard

@synthesize bestTime, allTimes;

- (id)init {
    
    if (self = [super init]) {
        
        bestTime = [[NSString alloc] init];
        allTimes = [[NSMutableArray alloc] init];
        
    }
    
    return self;
    
}

- (id)initWithCoder:(NSCoder *)aDecoder {
    
    if (self = [super init]) {
        
        bestTime = [[aDecoder decodeObjectForKey:@"bestTime"] retain];
        allTimes = [[aDecoder decodeObjectForKey:@"allTimes"] retain];
        
    }
    
    return self;
    
}

- (void)encodeWithCoder:(NSCoder *)aCoder {
    
    [aCoder encodeObject:bestTime forKey:@"bestTime"];
    [aCoder encodeObject:allTimes forKey:@"allTimes"];
    
}

- (void)dealloc {
    
    [bestTime release];
    [allTimes release];
    [super dealloc];
    
}

@end



通过在类里声明两个方法nitWithCoder: / encodeWithCoder:,使我们的类符合NSCoding协议---当然我们已经在类里实现了这两个方法。
当ScoreCard 类的对象被encoded时,必须保证它的实例变量也一起被encoded.正如你看到的,ScoreCard对象在[encodeWithCoder:]对此进行了相应处理。

当然在 [initWithCoder:]方法里也做了相应的解码处理。在这里,ScoreCard对象通过NSCoder参数传过来的信息来初始化它的实例变量。这是一个优雅的解决

办法;我们没有必要去关注编码/解码的过程,而ScoreCard从放进去和它的实例变量都能当成常规对象看待。

对于encode/decode方法在什么时候会被唤醒你可能有一些疑问,那么请看接下来我们其它对象的代码,一切都会变得很明了。


// Athlete.h
#import <Foundation/Foundation.h>

@interface Athlete : NSObject <NSCoding> {
    
    NSString *name;
    NSString *bio;
    NSString *phoneNumber;
    ScoreCard *scoreCard;
    BOOL eligible;
    
}

@property (copy) NSString *name, *bio, *phoneNumber;
@property (retain) ScoreCard *scoreCard;
@property (getter=isEligible) BOOL eligible;

- (void)print;

@end


@implementation Athlete

@synthesize name, bio, phoneNumber, scoreCard, eligible;

- (id)init {
    
    if (self = [super init]) {
    
        name = [[NSString alloc] init];
        bio = [[NSString alloc] init];
        phoneNumber = [[NSString alloc] init];
        scoreCard = [[ScoreCard alloc] init];
        eligible = YES;
        
    }
    
    return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder {
    
    if (self = [super init]) {
    
        name = [[aDecoder decodeObjectForKey:@"name"] retain];
        bio = [[aDecoder decodeObjectForKey:@"bio"] retain];
        phoneNumber = [[aDecoder decodeObjectForKey:@"phoneNumber"] retain];
        scoreCard = [[aDecoder decodeObjectForKey:@"scoreCard"] retain];
        eligible = [aDecoder decodeBoolForKey:@"eligible"];
        
    }
        
    return self;
    
}

- (void)encodeWithCoder:(NSCoder *)aCoder {
    
    [aCoder encodeObject:name forKey:@"name"];
    [aCoder encodeObject:bio forKey:@"bio"];
    [aCoder encodeObject:phoneNumber forKey:@"phoneNumber"];
    [aCoder encodeObject:scoreCard forKey:@"scoreCard"];
    [aCoder encodeBool:eligible forKey:@"eligible"];
    
}

- (void)print {
    
    NSLog(@"Name: %@\nBio: %@\nTel: %@\n\nBest Time: %@\n\nAll Times:", name, bio, phoneNumber, [scoreCard bestTime]);
    for (NSString *time in [scoreCard allTimes])
        NSLog(@"%@", time);
    
}

- (void)dealloc {
    
    [name release];
    [bio release];
    [phoneNumber release];
    [scoreCard release];
    [super dealloc];
    
}
@end


实际上这里没有什么新东西,除了新定义了一个BOOL变量外。 只要注意 我们的 编码/解码 的方法来处理 这种类型的 原始数据 的微小变化。
我写了一个 快速打印的方法 ,所以 我们 可以很容易地 测试程序的输出。
同时,正如你看到的,Athlete对象中包含一个ScoreCard实例变量。当一个Athlete对象encoded/decoded时,ScoreCard实例变量也进行同样的操作(当然所有的实例变量

都会进行这样的操作,我特意指出ScoreCard实例变量只是因为它是一个定制的对象)。


// Roster.h
#import <Foundation/Foundation.h>

@interface Roster : NSObject <NSCoding> {
    
    NSMutableArray *athletes;
    int rank;
    
}

@property (retain) NSMutableArray *athletes;
@property int rank;

- (void)print;
- (void)addAthlete:(Athlete *)athlete;

@end

@implementation Roster

@synthesize rank, athletes;

- (id)init {
    
    if (self = [super init]) {
    
        rank = 0;
        athletes = [[NSMutableArray alloc] init];
        
    }
    
    return self;
    
}

- (id)initWithCoder:(NSCoder *)aDecoder {
    
    if (self = [super init]) {
    
        athletes = [[aDecoder decodeObjectForKey:@"athletes"] retain];
        rank = [aDecoder decodeIntForKey:@"rank"];
        
    }
    
    return self;
    
}

- (void)encodeWithCoder:(NSCoder *)aCoder {
    
    [aCoder encodeObject:athletes forKey:@"athletes"];
    [aCoder encodeInt:rank forKey:@"rank"];
    
}

- (void)addAthlete:(Athlete *)athlete {

    [athletes addObject:athlete];
    
}

- (void)print {
    
    NSLog(@"Roster info:\nRank: %d", rank);
    for (Athlete *athlete in athletes)
        NSLog(@"%@", [athlete name]);
    
}

- (void)dealloc {
    
    [athletes release];
    [super dealloc];
}

@end


这里,同样的处理;这次我负责初始化和打印选手名字的工作。

现在运行测试.

static NSString *names [] = { @"Jeff Beck", @"Eric Clapton", @"Angus Young", @"John Doe", @"Jane Doe", @"Shaun White", @"Flavius Josephus" };

// function to create a roster. in real life, this wouldn't be used, but we're just testing now
Roster * create() {

    NSMutableArray *scoresArray = [NSMutableArray arrayWithObjects:@"15:09:34", @"17:54:01", @"19:56:08", nil];
    
    Roster *roster = [[Roster alloc] init];
    for (int i = 0; i < 7; ++i) {
    
        Athlete *athlete = [[Athlete alloc] init];
        [athlete setName:names[i]];
        [athlete setBio:@"I'm a boss"];
        [athlete setPhoneNumber:@"867-5309"];
        [athlete.scoreCard setBestTime:@"12:30:34"];
        [athlete.scoreCard setAllTimes:scoresArray];
        
        [roster addAthlete:athlete];
        
    }
    
    return [roster autorelease];
    
}

int main (int argc, char **argv) {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

// create and archive a roster
    Roster *roster = create();
    [NSKeyedArchiver archiveRootObject:roster toFile:@"/roster.archive"];

// unarchive roster
//  Roster *roster = [NSKeyedUnarchiver unarchiveObjectWithFile:@"/roster.archive"];
//  
//  [roster print];
//  
//  for (Athlete *athlete in [roster athletes])
//    [athlete print];
        
    [pool drain];
    return 0;
}


程序第一次运行时,一个Roster对象被创建,填充和存档。
去除下面几行的注释,你就可心从档案里创建一个Roster对象。

 

你可能感兴趣的:(Path,interface,getter,methods,archive,testing)