原文地址:点击打开链接
代码如下:
- 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对象。
本文介绍如何使用NSKeyedArchiver实现iOS应用程序的数据持久化。通过具体实例展示了如何为复杂对象如ScoreCard、Athlete及Roster类实现NSCoding协议,从而支持对象的归档与解档。
378

被折叠的 条评论
为什么被折叠?



