NSKeyedArchiver的基础用法

来源:互联网 发布:java 语法 基础 编辑:程序博客网 时间:2024/05/10 22:15

原文地址:点击打开链接

代码如下:

[cpp] view plaincopyprint?
  1. NSString *str = @"abc";  
  2. NSString *astr = @"efg";  
  3. NSArray *Array = [NSArray arrayWithObjects:str, astr, nil];  
  4.        
  5. //保存数据  
  6. NSString *Path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; NSString *filename = [Path stringByAppendingPathComponent:@"test.plist"];  
  7. [NSKeyedArchiver archiveRootObject:Array toFile:filename];  
  8.        
  9. str = @"a";  
  10. astr = @"";  
  11.        
  12. //加载数据  
  13. NSArray *arr = [NSKeyedUnarchiver unarchiveObjectWithFile: filename];  
  14. str = [arr objectAtIndex:0];  
  15. astr =  [arr objectAtIndex:1];  
  16.        
  17. NSLog(@"str:%@",str);  
  18. NSLog(@"astr:%@",astr);  


 

 

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

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

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

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

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

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

这里是我们简单的类代码

[cpp] view plaincopyprint?
  1. // ScoreCard.h  
  2. #import <Foundation/Foundation.h>  
  3.   
  4. @interface ScoreCard : NSObject <NSCoding> {  
  5.       
  6.     NSString *bestTime;  
  7.     NSMutableArray *allTimes;  
  8.       
  9. }  
  10.   
  11. @property (copy) NSString *bestTime;  
  12. @property (copy) NSMutableArray *allTimes;  
  13.   
  14. // other methods not relevant to this tutorial go here  
  15.   
  16. @end  
  17.   
  18. @implementation ScoreCard  
  19.   
  20. @synthesize bestTime, allTimes;  
  21.   
  22. - (id)init {  
  23.       
  24.     if (self = [super init]) {  
  25.           
  26.         bestTime = [[NSString alloc] init];  
  27.         allTimes = [[NSMutableArray alloc] init];  
  28.           
  29.     }  
  30.       
  31.     return self;  
  32.       
  33. }  
  34.   
  35. - (id)initWithCoder:(NSCoder *)aDecoder {  
  36.       
  37.     if (self = [super init]) {  
  38.           
  39.         bestTime = [[aDecoder decodeObjectForKey:@"bestTime"] retain];  
  40.         allTimes = [[aDecoder decodeObjectForKey:@"allTimes"] retain];  
  41.           
  42.     }  
  43.       
  44.     return self;  
  45.       
  46. }  
  47.   
  48. - (void)encodeWithCoder:(NSCoder *)aCoder {  
  49.       
  50.     [aCoder encodeObject:bestTime forKey:@"bestTime"];  
  51.     [aCoder encodeObject:allTimes forKey:@"allTimes"];  
  52.       
  53. }  
  54.   
  55. - (void)dealloc {  
  56.       
  57.     [bestTime release];  
  58.     [allTimes release];  
  59.     [super dealloc];  
  60.       
  61. }  
  62.   
  63. @end  



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

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

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

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


[cpp] view plaincopyprint?
  1. // Athlete.h  
  2. #import <Foundation/Foundation.h>  
  3.   
  4. @interface Athlete : NSObject <NSCoding> {  
  5.       
  6.     NSString *name;  
  7.     NSString *bio;  
  8.     NSString *phoneNumber;  
  9.     ScoreCard *scoreCard;  
  10.     BOOL eligible;  
  11.       
  12. }  
  13.   
  14. @property (copy) NSString *name, *bio, *phoneNumber;  
  15. @property (retain) ScoreCard *scoreCard;  
  16. @property (getter=isEligible) BOOL eligible;  
  17.   
  18. - (void)print;  
  19.   
  20. @end  
  21.   
  22.   
  23. @implementation Athlete  
  24.   
  25. @synthesize name, bio, phoneNumber, scoreCard, eligible;  
  26.   
  27. - (id)init {  
  28.       
  29.     if (self = [super init]) {  
  30.       
  31.         name = [[NSString alloc] init];  
  32.         bio = [[NSString alloc] init];  
  33.         phoneNumber = [[NSString alloc] init];  
  34.         scoreCard = [[ScoreCard alloc] init];  
  35.         eligible = YES;  
  36.           
  37.     }  
  38.       
  39.     return self;  
  40. }  
  41.   
  42. - (id)initWithCoder:(NSCoder *)aDecoder {  
  43.       
  44.     if (self = [super init]) {  
  45.       
  46.         name = [[aDecoder decodeObjectForKey:@"name"] retain];  
  47.         bio = [[aDecoder decodeObjectForKey:@"bio"] retain];  
  48.         phoneNumber = [[aDecoder decodeObjectForKey:@"phoneNumber"] retain];  
  49.         scoreCard = [[aDecoder decodeObjectForKey:@"scoreCard"] retain];  
  50.         eligible = [aDecoder decodeBoolForKey:@"eligible"];  
  51.           
  52.     }  
  53.           
  54.     return self;  
  55.       
  56. }  
  57.   
  58. - (void)encodeWithCoder:(NSCoder *)aCoder {  
  59.       
  60.     [aCoder encodeObject:name forKey:@"name"];  
  61.     [aCoder encodeObject:bio forKey:@"bio"];  
  62.     [aCoder encodeObject:phoneNumber forKey:@"phoneNumber"];  
  63.     [aCoder encodeObject:scoreCard forKey:@"scoreCard"];  
  64.     [aCoder encodeBool:eligible forKey:@"eligible"];  
  65.       
  66. }  
  67.   
  68. - (void)print {  
  69.       
  70.     NSLog(@"Name: %@\nBio: %@\nTel: %@\n\nBest Time: %@\n\nAll Times:", name, bio, phoneNumber, [scoreCard bestTime]);  
  71.     for (NSString *time in [scoreCard allTimes])  
  72.         NSLog(@"%@", time);  
  73.       
  74. }  
  75.   
  76. - (void)dealloc {  
  77.       
  78.     [name release];  
  79.     [bio release];  
  80.     [phoneNumber release];  
  81.     [scoreCard release];  
  82.     [super dealloc];  
  83.       
  84. }  
  85. @end  


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

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


[cpp] view plaincopyprint?
  1. // Roster.h  
  2. #import <Foundation/Foundation.h>  
  3.   
  4. @interface Roster : NSObject <NSCoding> {  
  5.       
  6.     NSMutableArray *athletes;  
  7.     int rank;  
  8.       
  9. }  
  10.   
  11. @property (retain) NSMutableArray *athletes;  
  12. @property int rank;  
  13.   
  14. - (void)print;  
  15. - (void)addAthlete:(Athlete *)athlete;  
  16.   
  17. @end  
  18.   
  19. @implementation Roster  
  20.   
  21. @synthesize rank, athletes;  
  22.   
  23. - (id)init {  
  24.       
  25.     if (self = [super init]) {  
  26.       
  27.         rank = 0;  
  28.         athletes = [[NSMutableArray alloc] init];  
  29.           
  30.     }  
  31.       
  32.     return self;  
  33.       
  34. }  
  35.   
  36. - (id)initWithCoder:(NSCoder *)aDecoder {  
  37.       
  38.     if (self = [super init]) {  
  39.       
  40.         athletes = [[aDecoder decodeObjectForKey:@"athletes"] retain];  
  41.         rank = [aDecoder decodeIntForKey:@"rank"];  
  42.           
  43.     }  
  44.       
  45.     return self;  
  46.       
  47. }  
  48.   
  49. - (void)encodeWithCoder:(NSCoder *)aCoder {  
  50.       
  51.     [aCoder encodeObject:athletes forKey:@"athletes"];  
  52.     [aCoder encodeInt:rank forKey:@"rank"];  
  53.       
  54. }  
  55.   
  56. - (void)addAthlete:(Athlete *)athlete {  
  57.   
  58.     [athletes addObject:athlete];  
  59.       
  60. }  
  61.   
  62. - (void)print {  
  63.       
  64.     NSLog(@"Roster info:\nRank: %d", rank);  
  65.     for (Athlete *athlete in athletes)  
  66.         NSLog(@"%@", [athlete name]);  
  67.       
  68. }  
  69.   
  70. - (void)dealloc {  
  71.       
  72.     [athletes release];  
  73.     [super dealloc];  
  74. }  
  75.   
  76. @end  


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

现在运行测试.

[cpp] view plaincopyprint?
  1. static NSString *names [] = { @"Jeff Beck", @"Eric Clapton", @"Angus Young", @"John Doe", @"Jane Doe", @"Shaun White", @"Flavius Josephus" };  
  2.   
  3. // function to create a roster. in real life, this wouldn't be used, but we're just testing now  
  4. Roster * create() {  
  5.   
  6.     NSMutableArray *scoresArray = [NSMutableArray arrayWithObjects:@"15:09:34", @"17:54:01", @"19:56:08", nil];  
  7.       
  8.     Roster *roster = [[Roster alloc] init];  
  9.     for (int i = 0; i < 7; ++i) {  
  10.       
  11.         Athlete *athlete = [[Athlete alloc] init];  
  12.         [athlete setName:names[i]];  
  13.         [athlete setBio:@"I'm a boss"];  
  14.         [athlete setPhoneNumber:@"867-5309"];  
  15.         [athlete.scoreCard setBestTime:@"12:30:34"];  
  16.         [athlete.scoreCard setAllTimes:scoresArray];  
  17.           
  18.         [roster addAthlete:athlete];  
  19.           
  20.     }  
  21.       
  22.     return [roster autorelease];  
  23.       
  24. }  
  25.   
  26. int main (int argc, char **argv) {  
  27.     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];  
  28.   
  29. // create and archive a roster  
  30.     Roster *roster = create();  
  31.     [NSKeyedArchiver archiveRootObject:roster toFile:@"/roster.archive"];  
  32.   
  33. // unarchive roster  
  34. //  Roster *roster = [NSKeyedUnarchiver unarchiveObjectWithFile:@"/roster.archive"];  
  35. //    
  36. //  [roster print];  
  37. //    
  38. //  for (Athlete *athlete in [roster athletes])  
  39. //    [athlete print];  
  40.           
  41.     [pool drain];  
  42.     return 0;  
  43. }  


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