轉載自:http://blog.csdn.net/mad1989/article/details/9106475
今天記錄一下學習 NSKeyedArchiver、NSKeyedUnarchiver ,主要用在ios數據存儲上,數據從內存存儲到閃存上,這個過程稱爲歸檔。
一、創建一個數據模型(自定義類)
現在就以大家常見的Student的爲例,這個模型有5個參數:name、age、weight、hobby、others
Student.h
- #import <Foundation/Foundation.h>
- @interface Student : NSObject<NSCoding,NSCopying>
- @property(copy,nonatomic) NSString *name;
- @property(assign,nonatomic) int age;
- @property(assign,nonatomic) double weight;
- @property(copy,nonatomic) NSArray *hobby;
- @property(copy,nonatomic) NSDictionary *others;
- @end
Student.m
- #import "Student.h"
- #define knameKey @"name"
- #define kageKey @"age"
- #define kweightKey @"weight"
- #define khobbyKey @"hobby"
- #define kotherKey @"others"
- @implementation Student
- @synthesize name;
- @synthesize age;
- @synthesize weight;
- @synthesize hobby;
- @synthesize others;
- #pragma mark-NSCoding
- -(void)encodeWithCoder:(NSCoder *)aCoder{
- [aCoder encodeObject:name forKey:knameKey];
- [aCoder encodeInt:age forKey:kageKey];
- [aCoder encodeDouble:weight forKey:kweightKey];
- [aCoder encodeObject:hobby forKey:khobbyKey];
- [aCoder encodeObject:others forKey:kotherKey];
- }
- -(id)initWithCoder:(NSCoder *)aDecoder{
- if (self == [super init]) {
- name = [aDecoder decodeObjectForKey:knameKey];
- age = [aDecoder decodeIntForKey:kageKey];
- weight = [aDecoder decodeDoubleForKey:kweightKey];
- hobby = [aDecoder decodeObjectForKey:khobbyKey];
- others = [aDecoder decodeObjectForKey:kotherKey];
- }
- return self;
- }
- #pragma mark-NSCopying
- -(id)copyWithZone:(NSZone *)zone{
- Student *copy = [[[self class] allocWithZone:zone] init];
- copy.name = [self.name copyWithZone:zone];
- copy.age = self.age;
- copy.weight = self.weight;
- copy.hobby = [self.hobby copyWithZone:zone];
- copy.others = [self.others copyWithZone:zone];
- return copy;
- }
- @end
通過以上的代碼我們可以看出,要實現對數據模型的歸檔,需要我們實現NScoding協議,NScoping(copy協議是爲了模型數據可以複製,對於歸檔而言,不是必須要實現)
NScoding協議需要實現兩個方法:
-(void)encodeWithCoder:(NSCoder *)aCoder 以keyValue形式對基本數據類型Encoding
-(id)initWithCoder:(NSCoder *)aDecoder 以keyValue形式對基本數據類型Decoding,返回數據模型本身
-(id)copyWithZone:(NSZone *)zone NScopying協議的方法,目的爲了實現數據模型的copy,如下實例:
- Student *s1 = [[Student alloc] init];
- Student *s2 = [s1 copy];
- NSLog(@"s1:%@",s1);
- NSLog(@"s2:%@",s2);
Log控制檯輸出:
2013-06-16 16:19:36.157 ArchiveDemo[1357:c07] s1:<Student: 0x8875340>
2013-06-16 16:19:36.158 ArchiveDemo[1357:c07] s2:<Student: 0x8875360>
二、ViewController.xib添加幾個針對數據模型的可編輯組件:
三、接下來就是在Viewcontroller.m中的操作,首先添加一個內部使用的方法,返回要保存到閃存的位置:
- -(NSString *) getFilePath{
- NSArray *array = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
- return [[array objectAtIndex:0] stringByAppendingPathComponent:kFileName];
- }
在ViewDidLoad方法裏,每次viewController初始化時,讀取路徑下的歸檔文件,讀取數據模型數據。同時添加一個通知每當按下Home鍵時,數據及時歸檔到閃存中。
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- if ([[NSFileManager defaultManager] fileExistsAtPath:[self getFilePath]]) {
- NSLog(@"filePAth:%@",[self getFilePath]);
- NSData *data = [[NSData alloc] initWithContentsOfFile:[self getFilePath]];
- NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
- //解檔出數據模型Student
- Student *mStudent = [unarchiver decodeObjectForKey:kDataKey];
- [unarchiver finishDecoding];//一定不要忘記finishDecoding,否則會報錯
- //接檔後就可以直接使用了(賦值到相應的組件屬性上)
- self.nameLabel.text = mStudent.name;
- self.ageLabel.text = [NSString stringWithFormat:@"%d",mStudent.age];
- self.weightLabel.text = [NSString stringWithFormat:@"%f",mStudent.weight];
- self.hobbyTextField.text = [mStudent.hobby objectAtIndex:0];
- self.othersTextView.text = [mStudent.others objectForKey:@"other"];
- [unarchiver release];
- [data release];
- }
- //添加一個廣播,用於註冊當用戶按下home鍵時,歸檔數據到閃存中
- UIApplication *app = [UIApplication sharedApplication];
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(saveAppDataWhenApplicationWillResignActive) name:UIApplicationWillResignActiveNotification object:app];
- }
四、某一操作需要保存數據的時候,及時歸檔到閃存中
- /**
- *當用戶按下Home鍵,返回桌面時,歸檔當前數據到指定文件路徑下
- */
- -(void) saveAppDataWhenApplicationWillResignActive:(NSNotification*) notification{
- Student *saveStudent = [[Student alloc] init];
- saveStudent.name = self.nameLabel.text;
- saveStudent.age = [self.ageLabel.text intValue];
- saveStudent.weight = [self.weightLabel.text doubleValue];
- saveStudent.hobby = [NSArray arrayWithObjects:self.hobbyTextField.text, nil];
- saveStudent.others = [NSDictionary dictionaryWithObjectsAndKeys:self.othersTextView.text,@"other",nil];
- NSMutableData *data = [[NSMutableData alloc] init];
- NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
- [archiver encodeObject:saveStudent forKey:kDataKey];
- [archiver finishEncoding];
- [data writeToFile:[self getFilePath] atomically:YES];
- [data release];
- [archiver release];
- [saveStudent release];
- }
運行效果:
重新運行後:
歸檔這種保存方式缺點就是沒有屬性列表(NSuserDefault)速度快,因爲它每次都要把文件保存到閃存中,優點是可以創建自己想要的數據模型,然後統一以模型方式存儲,比屬性列表要過分依賴Key要省心。
目前就記錄這麼多,以後再有的話再補充,如果有什麼錯誤歡迎大家指出,一起學習,進步。