在Cocoa世界中,术语“归档”是指另一种形式的序列化,它可以实现对任何对象的序列化。使用对模型对象进行归档的技术可以轻松将复杂的对象写入文件,然后再从中读取它们。只要在类中实现的每个属性都是标量(如int或float)或都是符合NSCoding协议的某个类的实例,就可以对该对象进行归档。由于大多数支持数据存储的Foundation和Cocoa Touch类都符合NSCoding,因此对于大多数类来说,归档相对而言比较容易实现。为了增加灵活性,在使用应用中,NSCoding协议最好与NSCopying协议一起使用,该协议运行复制对象。

1)符合NSCoding

NSCoding协议申明了两个方法,这两个方法都是必需的。一个方法将对象编码到归档中;另一个方法通过对归档解码来创建一个新的对象。这两个方法都传递一个NSCoder实例,我们继续根据以上一篇博文中的属性序列化中的例子为基础来说明。首先,我们创建一个FourLines类,该类的头文件如下代码如下,主要申明几个属性。

#import <Foundation/Foundation.h>
#define kField1Key @"field1"
#define kField2Key @"field2"
#define kField3Key @"field3"
#define kField4Key @"field4" @interface FourLines : NSObject<NSCoding,NSCopying>
{
NSString* field1;
NSString* field2;
NSString* field3;
NSString* field4;
} @property (nonatomic, retain) NSString* field1;
@property (nonatomic, retain) NSString* field2;
@property (nonatomic, retain) NSString* field3;
@property (nonatomic, retain) NSString* field4;

接下来,需要实现 NSCoding协议的第一个方法encodeWithCoder,该方法主要是对对象进行编码,代码如下:

// NSCoding
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:field1 forKey:kField1Key];
[aCoder encodeObject:field2 forKey:kField2Key];
[aCoder encodeObject:field3 forKey:kField3Key];
[aCoder encodeObject:field4 forKey:kField4Key];
}

上面代码将对象的每个实例变量进行了编码,因此,在对归档数据进行操作时,我们需要对编码的对象进行解码,因此 NSCoding的另一个方法就是实现对对象的解码功能,代码如下:

- (id)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super init])
{
self.field1 = [aDecoder decodeObjectForKey:kField1Key];
self.field2 = [aDecoder decodeObjectForKey:kField2Key];
self.field3 = [aDecoder decodeObjectForKey:kField3Key];
self.field4 = [aDecoder decodeObjectForKey:kField4Key];
}
return self;
}

2)实现NSCopying

实现了NSCoding协议的两个方法,接下来我们还要实现NSCopying协议中的copyWithZone方法,该方法可用于复制对象,与NSCoding中的initWithCoder很相似,所有需要做的只是创建一个同类对象,然后将该新实例的所有属性都设置为与该对象属性相同的只。该方法的代码如下:

// NSCopying
- (id)copyWithZone:(NSZone *)zone
{
FourLines* copy = [[[self class] allocWithZone:zone]init];
field1 = [self.field1 copy];
field2 = [self.field2 copy];
field3 = [self.field3 copy];
field4 = [self.field4 copy];
return copy;
}

3)对数据对象进行归档

从符合NSCoding的一个或多个对象创建归档相对比较容易,首先创建一个NSMutableData实例,用于包含编码的数据;然后创建一个NSKeyedArchiver实例,用于将对象归档到NSMutableData实例中。在这两个对象创建之后,就直接告知归档程序,将NSMutableData写入文件系统。本文在程序即将退出时,对数据进行归档,代码如下:

- (void)applicationWillTerminate:(NSNotification *)notification
{ FourLines* fourLines = [[FourLines alloc]init];
fourLines.field1 = field1.text;
fourLines.field2 = field2.text;
fourLines.field3 = field3.text;
fourLines.field4 = field4.text; NSMutableData* data = [[NSMutableData alloc]init];
NSKeyedArchiver* archiver = [[NSKeyedArchiver alloc]initForWritingWithMutableData:data];
[archiver encodeObject:fourLines forKey:kDataKey];
[archiver finishEncoding];
[data writeToFile:[self dataFilePath] atomically:YES];
}

4)从归档文件中加载数据

在程序重新启动或需要再次加载归档对象时,我们只要创建一个NSData实例,并创建一个NSKeyedUnarchiver对象对数据进行解码,该代码在viewDidLoad函数中实现,代码如下:

- (void)viewDidLoad
{
// Do any additional setup after loading the view, typically from a nib.
NSString* filePath = [self dataFilePath];
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath])
{
NSData* data = [[NSMutableData alloc]initWithContentsOfFile:[self dataFilePath]];
NSKeyedUnarchiver* unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
FourLines* fourLines = [unarchiver decodeObjectForKey:kDataKey];
[unarchiver finishDecoding];
field1.text = fourLines.field1;
field2.text = fourLines.field2;
field3.text = fourLines.field3;
field4.text = fourLines.field4;
} UIApplication* app = [UIApplication sharedApplication];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillTerminate:) name:UIApplicationWillTerminateNotification object:app]; [super viewDidLoad];
}

程序实现的功能与上一篇博文相同,实际上,这两个程序大致相似,改动的地方并不多。那么属性列表和对象归档又有什么优势呢?举个简单的例子:实现比较int , char, float ,double两个变量的大小,用C语言要些4个函数,在C++中有函数模板,对于实现类似功能的函数,通过模板实现,只需要一个函数就可以完成相同功能,模板函数不仅减少了代码编写量,而且提高了程序的可维护性,函数模板就类似这里的对象归档。

该实例的代码可以通过下面的连接下载:http://download.csdn.net/detail/kezunhai/6199397

iphone开发中数据持久化之——模型对象归档(二)的更多相关文章

  1. iphone开发中数据持久化之——属性列表序列化(一)

    数据持久化是应用程序开发过程中的一个基本问题,对应用程序中的数据进行持久化存储,有多重不同的形式.本系列文章将介绍在iphone开发过程中数据持久化的三种主要形式,分别是属性列表序列号.对象归档化以及 ...

  2. iphone开发中数据持久化之——嵌入式SQLite(三)

    前两篇分别讨论了使用属性列表的数据持久化.使用对象归档的数据持久化,本文将讨论第三个实现数据持久化的方法---嵌入式SQL数据库SQLite3.SQLite3在存储和检索大量数据方面非常有效.它还能够 ...

  3. IOS开发中数据持久化的几种方法--NSUserDefaults

    IOS开发中数据持久化的几种方法--NSUserDefaults IOS 开发中,经常会遇到需要把一些数据保存在本地的情况,那么这个时候我们有以下几种可以选择的方案: 一.使用NSUserDefaul ...

  4. objective C中数据持久化方式1--对象归档

    第一.数据持久化的方式: NSKeyedArchiver--对象归档 属性列表化(NSArray.NSDictionary.NSUserDefault) SQlite数据库.CoreData数据库 其 ...

  5. iOS开发中数据持久化

    使用几个小例子分别实现 归档NSKeyedArchiver.NSUserDefaults.plist文件数据存储,简单直观.代码地址

  6. iOS开发——数据持久化Swift篇&模型对象归档

    模型对象归档 import UIKit class ViewController: UIViewController { @IBOutlet weak var textField: UITextFie ...

  7. 解析iOS开发中的FirstResponder第一响应对象

    1. UIResonder 对于C#里所有的控件(例如TextBox),都继承于Control类.而Control类的继承关系如下: 代码如下: System.Object System.Marsha ...

  8. iPhone开发中从一个视图跳到另一个视图有三种方法:

    iPhone开发中从一个视图跳到另一个视图有三种方法:   1.self.view addSubView:view .self.window addSubView,需要注意的是,这个方法只是把页面加在 ...

  9. iphone 开发中使用zbar时遇到的几个典型问题解决方法。

    iphone 开发中使用zbar时遇到的几个典型问题解决方法.   在近期的一个ios项目中使用到了一个二维码扫描库(Qrcode)--ZBar, 期间遇到2个问题.   1. zbar下载后使用其l ...

随机推荐

  1. 【REDO】删除REDO LOG重做日志组后需要手工删除对应的日志文件(转)

    为保证重新创建的日志组成员可以成功创建,我们在删除日志组后需要手工删除对应的日志文件. 1.查看数据库当前REDO LOG日志相关信息1)查看日志组信息sys@ora10g> select * ...

  2. Java 异常分类

    1.java异常层次结构: 粉红色的是已检查异常(checked exceptions),其必须被 try{}catch语句块所捕获,或者在方法签名里通过throws子句声明.已检查异常必须在编译时被 ...

  3. Qt图片显示效率的比较 转

    转http://blog.sina.com.cn/s/blog_5c70dfc80100r257.html 在Qt中处理图片一般都要用到QImage类,但是QImage的对象不能够直接显示出来,要想能 ...

  4. 深入浅出Hadoop Mahout数据挖掘实战(算法分析、项目实战、中文分词技术)

    Mahout简介 Mahout 是 Apache Software Foundation(ASF) 旗下的一个开源项目, 提供一些可扩展的机器学习领域经典算法的实现,旨在帮助开发人员更加方便快捷地创建 ...

  5. Linux - 文件基本操作管理

    文件基本操作管理   复制文件和目录 格式: Cp 源文件(文件夹) 新目标文件名(文件夹) 相同目录下,指定文件名. 不同目录下,不需要指定文件名. 参数: –r:递归复制整个目录树. –v:再复制 ...

  6. JS - 侧边导航收缩伸展

    下载地址:http://www.lanrentuku.com/js/daohang-1162.html

  7. HTTP实现长连接(TTP1.1和HTTP1.0相比较而言,最大的区别就是增加了持久连接支持Connection: keep-alive)

    HTTP实现长连接 HTTP是无状态的 也就是说,浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束就中断连接.如果客户端浏览器访问的某个HTML或其他类型的Web页中包含有其他的Web ...

  8. Thinkphp入门三—框架模板、变量(47)

    原文:Thinkphp入门三-框架模板.变量(47) [在控制器调用模板] display()   调用当前操作名称的模板 display(‘名字’)  调用指定名字的模板文件 控制器调用模板四种方式 ...

  9. eval 捕获错误

    eval 捕获错误: [root@dr-mysql01 ~]# cat t1.pl use DBI; my $dbUser='zabbix'; my $user="root"; m ...

  10. 解决SVG跨浏览器兼容性问题

    Raphael JS:SVG/VML+JS实现跨浏览器的矢量图形实现方案 http://blog.csdn.net/tiewen/article/details/8535748 SVG那些小事儿 ht ...