ios数据存储——对象归档
2016-07-27 15:20
393 查看
归档:数据从内存与闪存相互转化,类似“序列化”,将数据转换成二进制字节数据
操作:有两种方式,第一种是单个对象作为root进行归档和恢复,一个对象一个文件;第二种,可以同时归档多个对象到一个文件
注意:归档自定义对象,需要实现NSCoding协议里的两个方法,举例说明:【preference】http://blog.csdn.net/mad1989/article/details/9106475
一、创建一个数据模型(自定义类)
现在就以大家常见的Student的为例,这个模型有5个参数:name、age、weight、hobby、others
Student.h
[cpp] view plain copy
#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
[cpp] view plain copy
#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,如下实例:
[cpp] view plain 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中的操作,首先添加一个内部使用的方法,返回要保存到闪存的位置:
[cpp] view plain copy
-(NSString *) getFilePath{
NSArray *array = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
return [[array objectAtIndex:0] stringByAppendingPathComponent:kFileName];
}
在ViewDidLoad方法里,每次viewController初始化时,读取路径下的归档文件,读取数据模型数据。同时添加一个通知每当按下Home键时,数据及时归档到闪存中。
[cpp] view plain copy
- (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];
}
四、某一操作需要保存数据的时候,及时归档到闪存中
[cpp] view plain copy
/**
*当用户按下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要省心。
操作:有两种方式,第一种是单个对象作为root进行归档和恢复,一个对象一个文件;第二种,可以同时归档多个对象到一个文件
注意:归档自定义对象,需要实现NSCoding协议里的两个方法,举例说明:【preference】http://blog.csdn.net/mad1989/article/details/9106475
一、创建一个数据模型(自定义类)
现在就以大家常见的Student的为例,这个模型有5个参数:name、age、weight、hobby、others
Student.h
[cpp] view plain copy
#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
[cpp] view plain copy
#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,如下实例:
[cpp] view plain 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中的操作,首先添加一个内部使用的方法,返回要保存到闪存的位置:
[cpp] view plain copy
-(NSString *) getFilePath{
NSArray *array = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
return [[array objectAtIndex:0] stringByAppendingPathComponent:kFileName];
}
在ViewDidLoad方法里,每次viewController初始化时,读取路径下的归档文件,读取数据模型数据。同时添加一个通知每当按下Home键时,数据及时归档到闪存中。
[cpp] view plain copy
- (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];
}
四、某一操作需要保存数据的时候,及时归档到闪存中
[cpp] view plain copy
/**
*当用户按下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要省心。
相关文章推荐
- iOS 10即将来袭!升级你的iOS开发装备
- iOS开发 ☞ __block,__weak,__strong
- 【iOS】Masonry使用案例讲解
- iOS数据解析
- iOS开发--用企业证书生成IPA包遇到的坑
- ios 银行卡号或身份证号按一定的个数分开显示
- ios加载图片内存优化
- iOS 10 SDK 新特性
- iOS try catch的使用
- 关于 iOS 10 中 ATS 的问题
- Nagios新添加的hosts和services有时显示,有时不显示问题解决
- iOS 单元测试
- IOS获取设备的IP
- 关于系统(ios7+)自带的向右滑动手势返回上一个界面的一个问题
- inux查看磁盘读写性能(iostat命令)的方法
- ios终端使用brew安装工具
- [编写高质量iOS代码的52个有效方法](七)内存管理(上)
- iOS - 大文件下载(task and session)
- iOS开发-键盘通知
- iOS开发 取消当前页面侧滑返回手势 监听当前页面的侧滑返回操作