代码如下:
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
当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
我写了一个 快速打印的方法 ,所以 我们 可以很容易地 测试程序的输出。
同时,正如你看到的,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对象。