ios数据存储之--对模型对象归档(NSKeyedArchiver、NSKeyedUnarchiver)



今天记录一下学习 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要省心。


目前就记录这么多,以后再有的话再补充,如果有什么错误欢迎大家指出,一起学习,进步。




评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值