OC基础17:归档
"OC基础"这个分类的文章是我在自学Stephen G.Kochan的《Objective-C程序设计第6版》过程中的笔记。
1、归档即是用某种格式把一个或多个对象保存起来,以便以后还原回来的一个过程。一般归档数据有两种方法:属性列表归档和带键值的归档。
2、使用XML属性列表进行归档:
(1)、Mac OS X上的应用程序使用XML属性列表(或plists)来存储诸如默认参数选择、应用程序设置和配置信息这样的一些数据。然而这些列表的归档用途是有限的,因为当某个数据结构创建属性列表时,没有保存特定的对象类,没有存储对同一对象的多个引用,也没有保持对象的可变性;
(2)、如果你的对象是NSString、NSDictionary、NSArray、NSData或NSNumber对象,你可以使用在这些类中实现的writeToFile:atomically:方法将数据写到文件中。该方法可以使用XML属性列表的格式写出数据。以下代码演示了如何将字典作为属性列表写入文件中,和如何读取出来:
...
NSDictionary *glossary = [NSDictionary dictionaryWithObjectsAndKeys:
@"A class defined so other class can inherit from it.",@"abstract class",
@"To implement all the methods defined in a protocol.",@"adopt",
@"Storing an object for later use.",@"archiving",
nil
];
if([glossary writeToFile:@"glossary" atomically:YES] == NO)
NSLog(@"Save to file failed!");
...
NSDictionary *readgloss;
readgloss = [NSDictionary dictionaryWithContentsOfFile:@"glossary"];
for(NSString *key in readgloss) {
NSLog(@"%@: %@",key,[readgloss objectForKey:key]);
}
...
(3)、其中writeToFile:atomically:消息被发送给字典对象glossary,使字典以属性列表的形式写入到文件glossary中。atomically参数被设置为YES,表示希望首先将字典写入临时备份文件中,并且一旦成功,再把最终数据转移到名为glossary的制定文件中。这是一种安全措施,它保护文件在一些情况下(如系统在执行操作的过程中崩溃时)免受破坏。在这种情况下原始的glossary文件(如果该文件已经存在)不会受到损害;
(4)、writeToFile:atomically:所创建的glossary文件,内容一般是这样的:
<dict>
<key>abstract class</key>
<string>A class defined so other class can inherit from it.</string>
<key>adopt</key>
<string>To implement all the methods defined in a protocol.</string>
<key>archiving</key>
<string>Storing an object for later use.</string>
</dict>
(5)、根据字典创建属性列表时,字典中的键必须全都是NSString对象。数组的元素或字典中的值可以是NSString、NSArray、NSDictionary、NSData或NSNumber等其他对象;
(6)、如果要将文件中的XML属性列表读入程序中,要使用dictionaryWithContentsOfFile:方法或arrayWithContentsOfFile:方法。要读取数据则用dataWithContentsOfFile:方法,要读取字符串对象则用stringWithContentsOfFile:方法。
3、使用NSKeyedArchiver归档:
(1)、要将各种类型的对象(不仅仅是字符串、数组和字典类型的对象)存储到文件中,有一种更灵活的方法,就是利用NSKeyedArchiver类创建带键的档案来完成;
(2)、在带键的归档中,每个归档字段都有一个名称。归档某个对象时,会为它提供一个名称,即键。从归档中检索该对象时,是根据这个键来检索的。这样可以按照任意的顺序将对象写入归档并进行检索。另外,如果向类添加了新的实例变量或删除了实例变量,程序也可以进行处理;
(3)、另外,iPhone SDK中没有提供NSArchiver。如果想在iPhone上使用归档功能,则必须使用NSKeyedArchiver;
(4)、以下代码演示了如何归档和读取:
...
NSDictionary *glossary = [NSDictionary dictionaryWithObjectsAndKeys:
@"A class defined so other class can inherit from it.",@"abstract class",
@"To implement all the methods defined in a protocol.",@"adopt",
@"Storing an object for later use.",@"archiving",
nil
];
[NSKeyedArchiver archiveRootObject:glossary toFile:@"glossary.archive"];
...
NSDictionary *readglossary;
readglossary = [NSKeyedUnarchiver unarchiveObjectWithFile:@"glossary.archive"];
for(NSString *key in readglossary) {
NSLog(@"%@: %@",key,[readglossary objectForKey:key]);
}
...
4、归档自定义类:
(1)、归档自定义类,首先要实现<NSCoding>协议,然后实现encodeWithCoder:方法和initWithCoder:方法;
(2)、以AddressCard类为例,首先要实现<NSCoding>协议:
@interface AddressCard: NSObject <NSCoding>
然后在@implementation部分添加以下方法:
-(void) encodeWithCoder: (NSCoder *) encoder {
[super encodeWithCoder: encoder];
[encoder encodeObject: name forKey: @ “AddressCardName”];
[encoder encodeObject: email forKey: @ “AddressCardEmail”];
}
-(id) initWithCoder: (NSCoder *) decoder {
self = [super initWithCoder: decoder];
name = [decoder decodeObjectForKey: @”AddressCardName”];
email = [decoder decodeObjectForKey: @”AddressCardEmail”];
return self;
}
(3)、由于name和email两个变量都是NSString类对象,所以可以使用encodeWithObject:方法对它们进行编码;
(4)、有可能会有子类继承了实例变量并且也进行归档,那么如果某个实例变量归档时的key只使用变量名的,就有可能会出现冲突。所以在指定key的时候,在实例变量名前加上类名;
(5)、如果父类也有编码和解码方法,才需要使用super语句;
(6)、bool、int、float和double等基本数据类型有各自对应的编码和解码方法;
(7)、归档和解码的方法如下:
...
if([NSKeyedArchiver archiveRootObject: ac toFile: @”addresscard.arch”] == NO){
//ac是一个AddressCard类的对象
NSLog(@”archiving failed”);
}
...
ac = [NSKeyedUnarchiver unarchiveObjectWithFile: @”addresscard.arch”];
...
(8)、如果一个类中含有多个类型的实例变量,则在重载encodeWithCoder和initWithCoder两个方法的时候,要对应使用不同的编码方法和解码方法,假如一个类Foo,包含了3个不同类型的实例变量,那么重载方法如下:
...
-(void)encodeWithCoder: (NSCoder *) encoder {
[encoder encodeObject: strVal forKey: @”FooStrVal”];
[encoder encodeInt: intVal forKey: @”FooIntVal”];
[encoder encodeFloat: floatVal forKey: @”FooFloatVal”];
}
...
-(id) initWithCoder: (NSCoder *) decoder {
strVal = [decoder decodeObjectForKey: @” FooStrVal”];
intVal = [decoder decodeIntForKey: @” FooIntVal”];
floatVal = [decoder decodeFloatForKey: @” FooFloatVal”];
return self;
}
...
5、使用NSData创建自定义档案:
(1)、有时可能想收集多个对象,并且将它们存储到单个档案文件中去,那么就要使用到NSData类;
(2)、以前面的AddressCard类和Foo类为例,两个类都已实现了encodeWithCoder:方法和initWithCoder:方法,那么可以使用encodeObject: forKey:方法把它们作为对象来归档;
(3)、归档的实现代码如下:
...
NSMutableData *dataArea;
NSKeyedArchiver *archiver;
...
dataArea = [NSMutableData data];
archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData: dataArea];
[archiver encodeObject: myCard forKey: @”myaddcard”];
[archiver encodeObject: myFoo forKey: @”myfoo”];
[archiver finishEncoding];
if([dataArea writeToFile: @”myArchive” atomically: YES] == NO){
NSLog(@”Archiver failed”);
}
...
(4)、其实就是使用定义过的encodeWithCode:r方法把对象归档到一个NSKeyedArchiver类对象archiver里,最后使用XML属性列表归档的方法把archiver的内容归档到文件中(archiver的内容会写在dataArea中),在过程中要注意,要向archiver发送一条finishEncoding的消息来结束编码过程;
(5)、从档案中恢复数据的方法如下:
...
NSData *dataArea;
NSKeyedUnarchiver *unarchiver;
...
dataArea = [NSData dataWithContentOfFile: @”myArchive”];
if(! dataArea) {
NSLog(@”can’t read back archiver file”);
return 1;
}
unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData: dataArea];
myCard = [unarchiver decodeObjectForKey: @”myaddcard”];
myFoo = [unarchiver decodeObjectForKey: @”myfoo”];
[unarchiver finishDecoding];
...
(6)、同样需要注意,最后要发送一条finishDecoding消息给unarchiver对象结束恢复;
6、可以使用Foundation的归档功能来创建对象的深复制:
(1)、假设有数组array1并且数组内有数据,可以使用NSData类对象data将它赋值到另一个空数组array2中去,语句如下:
...
data = [NSKeyedArchiver archivedDataWithRootObject: array1];
array2 = [NSKeyedUnarchiver unarchiveObjectWithData: data];
...
(2)、其实就是将array1的数据归档到data中,然后再恢复到array2中,执行的效果就是完全的深复制了;
(3)、甚至可以省略中间的data对象,只用一条语句来执行:
array2 = [NSKeyedUnarchiver unarchiveObjectWithData:
[NSKeyedArchiver archivedDataWithRootObject: array1]];
OC基础17:归档的更多相关文章
- OC基础(17)
ARC基本概念 ARC快速入门 ARC下的内存管理 ARC和MRC兼容和转换 *:first-child { margin-top: 0 !important; } body > *:last- ...
- OC基础笔记目录
OC基础(1) Objective-C简介 OC和C对比 第一个OC程序 面向对象思想 OC基础(2) 类与对象 类的设计 第一个OC类 对象方法的声明和实现 类方法的声明和实现 OC基础(3) 对象 ...
- iOS 阶段学习第11天笔记(OC基础知识)
iOS学习(OC语言)知识点整理 一.OC基础知识 1)#import 用于导入头文件,预处理阶段加载引用,只加载一次. 2)OC 依赖于Foundation框架下的头文件Foundation.h, ...
- OC基础13:数字、字符串和集合2
"OC基础"这个分类的文章是我在自学Stephen G.Kochan的<Objective-C程序设计第6版>过程中的笔记. 17.Foundation框架的数组是有序 ...
- OC基础10:基本的C语言特性1
"OC基础"这个分类的文章是我在自学Stephen G.Kochan的<Objective-C程序设计第6版>过程中的笔记. 1. 函数和方法的区别? (1).方法包 ...
- OC基础8:分类和协议
"OC基础"这个分类的文章是我在自学Stephen G.Kochan的<Objective-C程序设计第6版>过程中的笔记. 1.关于分类(category): (1) ...
- OC对象的归档及解档浅析
一般用在用户登录,保存这个用户的信息 对象归档,就是把内存中对象持久化. 对象解档,就是把持久化的对象读取到内存. oc中对象归档解档大致分为以下几种方法: 从数量上可以分为: 对单个对象归档解档 对 ...
- 【OC基础语法考试】
OC基础语法已经全部学完,但是这些知识只是最基础的,还有很多高级知识,这个可能需要后面慢慢的去学习才能体会到.接下来我会总结前面的OC基础语法,如果大家发现有什么不正确的地方,请指正,小弟是新生,多请 ...
- [.net 面向对象编程基础] (17) 数组与集合
[.net 面向对象编程基础] (17) 数组与集合 学习了前面的C#三大特性,及接口,抽象类这些相对抽象的东西以后,是不是有点很累的感觉.具体的东西总是容易理解,因此我们在介绍前面抽象概念的时候,总 ...
随机推荐
- XShell连接CentOS 7.2显示中文乱码问题的解决方法
背景 使用U盘往Windows主机.Linux主机传文件还是经常的事,但有时候文件名有中文, 传到Linux机器会有乱码,选择起来也很麻烦,最近刚好遇到,写下解决方法. 环境 Linux [root@ ...
- Java与面向对象
一.面向过程的思想和面向对象的思想 面向对象和面向过程的思想有着本质上的区别, 作为面向对象的思维来说,当你拿到一个问题时,你分析这个问题不再是第一步先做什么,第二步再做什么,这是面向过程的思维,你应 ...
- ios 读取通讯录数据
#import <Foundation/Foundation.h> @interface LoadingContactData : NSObject // 读取通讯录 + (Loading ...
- Highcharts 非常实用的Javascript统计图
Highcharts 官网: http://www.highcharts.com Highcharts 官网示例:http://www.highcharts.com/demo/ Highcharts ...
- MooseFS源代码分析(三)
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/ ...
- hibernate jpa 2.0 报错Hibernate cannot unwrap interface java.sql.Connection
今天在做报表的时候,利用Hibernate JPA 2.0需要获取数据库连接com.sql.Connection的时候获取不到,网上说用这种方式解决: entityManager.getTransac ...
- EffectiveC#8--确保0对于值类型数据是有效的(初始化问题)
1.决不要创建一个不包括0在内的枚举类型 2.举例如下: public enum Planet { Mercury = 1, Venus = 2, Earth = 3, Mars = 4, Jupit ...
- C#几种截取字符串的方法小结 (摘抄)
1.根据单个分隔字符用split截取 例如 string st="GT123_1"; string[] sArray=st.split("_"); 即可得到sA ...
- CSS基础笔记
之前没有开通好博客,笔记都记录在有道云,今天全部转过来!!! 1.当同一个html元素不止一个样式定义时,内联样式(在html元素内部)拥有最高的优先权:其他如内部样式表(位于<head> ...
- 我对 javascript 闭包的理解
学js的学到闭包,但是理解不深. 后来看了一下这篇文章: 地址:http://leepiao.blog.163.com/blog/static/4850313020112835355917/ 内容如下 ...