Objective-C下的NSCoding协议

原文出处:http://blog.csdn.net/likendsl/article/details/8513733

由于Sqlite数据库的blob数据和NSData的兼容比较好,我想尝试把一个NSArray存入Sqlite。Sqlite不支持数组的直接存储,所以我寻找了一些数组转化为NSData的方法。网上大多数的解决办法都是针对于字符数组,eg:

 NSArray*array01=
[[NSArrayalloc]initWithObjects:@"1",@"2",@"3",nil];

这种数组的解决办法很简单,循环遍历数组,然后把每次取出的NSString转码成NSData类型,然后对最终的NSData数据进行一次次的循环拼接,实现把数组中所有的字符串拼接成一个完整的NSData,eg:

 NSMutableData *data01
=[[NSMutableDataalloc]init];

    for (NSString *str in array01)
{

       NSString*newStr = [str stringByAppendingString:@","];//添加间隔,为了区分数组的每个元素

       NSData *temp =[newStr dataUsingEncoding:NSASCIIStringEncoding];//创建中间变量存储将nsstring转码成nsdata的数据

       [data01 appendData:temp];//data数据拼接到最终数据data01上

       [temp release];

    }

这样就实现了一个NSArray字符数组到NSData的转换。转换回来也很简单,把NSData转换成NSString,然后将NSString分割(这也就是我们为str添加末尾“,”的原因),eg:

 

     NSString *string01 = [[NSString alloc]initWithData:data01 encoding:NSUTF8StringEncoding];//将NSData数据转换成NSString类型数据

    NSArray *array02 = [string01 componentsSeparatedByString:@","];//字符串根据@“,”拆分成一个数组,将数组还原

        但是这样太麻烦了,经过了这么多次转换,我就在思考有没有更简单的方法,NSData和NSArray的直接转换。无意间看到了一个网站,我看到了一个方法,运用的是“归档”,下面我们来说一下这个方法的实现,eg:

 

NSData *data02 = [NSKeyedArchiver archivedDataWithRootObject:array01];//通过归档对NSArray进行转码,保存了数组的序列

一句代码就完成了!而且还保存了数组的有序性。转换回去也同样是一句话哦:),eg:

 

    NSArray *array02 = [NSKeyedUnarchiver unarchiveObjectWithData:data02];//通过发归档进行NSData反转码,返回有序列的数组

是不是很方便呢??不是很,是太方便了吧。但是这个时候问题又来了,我如果在数组里存放的不是NSString类型的对象呢,如果存了自定义的类,是否也可以自动跳转呢?(有点异想天开。。),于是我自己创建了一个Student类,尝试相同的方式转换,发现程序无法运行了,问了同事,他告诉了我这个秘密。原来所有原生的类都是实现了NSCoding协议,在归档的过程中进行了转码,所以才可以归档成功。我研究了一下NSCoding协议,下面是API给我们的信息:

 

NSCoding Protocol Reference

encodeWithCoder:

Encodes the receiver using a given archiver. (required)

- (void)encodeWithCoder:(NSCoder *)encoder

Parameters
encoder

An archiver object.

Availability
  • Available in iOS 2.0 and later.
Declared In

NSObject.h

initWithCoder:

Returns an object initialized from data in a given unarchiver.(required)

- (id)initWithCoder:(NSCoder *)decoder

Parameters
decoder

An unarchiver object.

Return Value

self, initialized using the datain decoder.

Availability
  • Available in iOS 2.0 and later.
Declared In

NSObject.h

NSCoding协议中只有两个方法,都是require的方法,一个是把本身的类进行转码,一个是逆转换成类对象,返回一个对象,我们实战一下这个协议的用法,看看是否好用,首先写一个自定义Student类:

@interfaceStudent : NSObject<NSCoding>

@property (nonatomic, retain) NSString *name;

@property (nonatomic, retain) NSString *ID;

-(Student *)initWithName :(NSString*)newName 

                 and : (NSString *)newID;

@end

Student类需要实现协议NSCoding,.m文件中是这样的:

 

@implementationStudent

@synthesize name = _name,ID = _ID;

 

//初始化学生类

-(Student *)initWithName:(NSString *)newName and:(NSString *)newID{

   self = [super init];

   if (self) {

       self.name = newName;

       self.ID= newID;

    }

   return self;

}

//学生类内部的两个属性变量分别转码

-(void)encodeWithCoder:(NSCoder *)aCoder{

   [aCoder encodeObject:self.name forKey:@"name"];

   [aCoder encodeObject:self.IDforKey:@"ID"];

}

//分别把两个属性变量根据关键字进行逆转码,最后返回一个Student类的对象

-(id)initWithCoder:(NSCoder *)aDecoder{

   if (self = [super init]) {

       self.name = [aDecoder decodeObjectForKey:@"name"];

       self.ID= [aDecoder decodeObjectForKey:@"ID"];

    }

   return self;

}

@end

自定义类Student实现了NSCoding协议以后,就可以进行归档转换了,具体实现:

 

   Student *stu1 = [[Student alloc]initWithName:@"124" and:@"111"];//学生对象stu1

   Student *stu2 = [[Student alloc]initWithName:@"223" and:@"222"];//学生对象stu2

   NSArray *stuArray =[NSArray arrayWithObjects:stu1,stu2, nil];//学生对象数组,里面包含stu1和stu2

   NSData *stuData = [NSKeyedArchiver archivedDataWithRootObject:stuArray];//归档

   NSLog(@"data = %@",stuData);

   NSArray *stuArray2 =[NSKeyedUnarchiver unarchiveObjectWithData:stuData];//逆归档

   NSLog(@"array2 = %@",stuArray2);

运行结果如下:

 

2012-09-25 10:44:24.944MagazineDemo[720:f803] data = <62706c69 73743030d4010203 0405082b 2c542474 6f705824 6f626a65 63747358 2476657273696f6e 59246172 63686976 6572d106 0754726f 6f748001 aa090a1117181920 24252655 246e756c 6cd20b0c 0d105a4e 532e6f62
6a65637473562463 6c617373 a20e0f80 02800680 09d31213 0c141516 524944546e616d65 80048003 80055331 32345331 3131d21a 1b1c1f58 24636c6173736573 5a24636c 6173736e 616d65a2 1d1e5753 74756465 6e74584e534f626a 65637457 53747564 656e74d3 12130c21 22168008 8007800553323233
53323232 d21a1b27 2aa22829 574e5341 72726179 584e534f626a6563 74574e53 41727261 79120001 86a05f10 0f4e534b 6579656441726368 69766572 00080011 0016001f 00280032 0035003a 003c0047004d0052 005d0064 00670069 006b006d 00740077 007c007e 008000820086008a 008f0098
00a300a6 00ae00b7 00bf00c6 00c800ca 00cc00d000d400d9 00dc00e4 00ed00f5 00fa0000 00000000 02010000 00000000002d0000 00000000 00000000 00000000 010c>

2012-09-25 10:44:24.944MagazineDemo[720:f803] array2 = (

   "<Student: 0x6883490>",

   "<Student: 0x68dd3c0>"

)

成功啦:)自定义类Student转码成功.

时间: 2024-09-29 09:50:41

Objective-C下的NSCoding协议的相关文章

VMware环境下的存储协议完全解析

随着虚拟化的普及加速,VMware环境下的应用更加普遍,因此绝对有必要对VMware环境下的存储协议进行研究与测试,特别是三大存储协议:光纤通道.iSCSI和NAS(NFS).通过VMware环境下的研究和测试,用户可以更好的理解自己虚拟化环境下的存储需求,从而让自身的业务运行的更为顺畅.这里先讨论三大协议中最为特别的iSCSI. 如果是创建一个VMware存储架构的话,你会基于以下几个因素作出决定:性能.成本和易用性.当然,还有其他像安全性和可靠性的一些问题.但是大多数用户更关心前者.另外还有

求助大神!!!!windows下的udp协议封装,实现网络通信

问题描述 求助大神!!!!windows下的udp协议封装,实现网络通信 在Qt平台上写的一个程序,是基于udp协议的网络通信,通过在一台电脑上打开两个命令窗口可以实现通信,为什么在两台电脑上就不行了?两台电脑连在同一个路由器下,已经关了防火墙!纠结了2天的问题了,求大神解决!!!!! 解决方案 先ping下看看通不通,本机的防火墙和路由的防火墙是否都关了.路由的防火墙是否禁用了广播.端口号,ip是否正确.程序先在本地双开能运行么?

云计算环境下密钥协商协议的应用与改进

云计算环境下密钥协商协议的应用与改进 任敏 为解决现有密钥协商协议在云计算环境下的适应性问题,深入分析云计算场景对密钥协商协议的安全需求,结合现有IKEv2协议的安全性能缺陷,采用puzzle机制.密钥材料及身份信息推迟传递等手段对IKEv2进行改进,提出了一种适应云计算网络环境的密钥协商协议IKE-C,有效提升了协议中响应者的抗拒绝服务(DoS)攻击能力,同时解决了中间人攻击导致发起者身份泄露的问题.还对两种协议的收敛时间进行了比较,仿真结果表明,在相同的网络规模下,IKE-C协议的收敛时间低

Linux下的网络协议分析工具:TCPDUMP入门

TCPDUMP简介 在传统的网络分析和测试技术中,嗅探器(sniffer)是最常见,也是最重要的技术之一.sniffer工具首先是为网络管理员和网络程序员进行网络分析而设计的.对于网络管理人员来说,使用嗅探器可以随时掌握网络的实际情况,在网络性能急剧下降的时候,可以通过sniffer工具来分析原因,找出造成网络阻塞的来源.对于网络程序员来说,通过sniffer工具来调试程序. 用过windows平台上的sniffer工具(例如,netxray和sniffer pro软件)的朋友可能都知道,在共享

流媒體】jrtplib—VS2010下RTP开源协议库JRTPLIB3.9.1编译

一.JRTPLIB简介 老外用C++编写的开源RTP协议库,用来进行实时数据传输,可以运行在 Windows.Linux. FreeBSD.Solaris.Unix和VxWorks 等多种操作系统上,主页为:http://research.edm.uhasselt.be/~jori/page/index.php?n=Main.HomePage   二.相关下载 jrtplib: http://research.edm.uhasselt.be/~jori/page/index.php?n=CS.J

asp.net下使用DIME协议上传文件_实用技巧

在某些Web Service的应用场景下,例如公文的传送,在Web Service返回结果的同时将word文档及其它附件返回,这时候可以使用DIME协议来进行文件的传输.使用它来传输不需要经过SOAP消息的序列化/反序列化,有很高的效率.当然这里要用到Web Services Enhancements (WSE) ,目前的最新版本为3.0.本文中所使用的版本为2.0sp2,有趣的是WSE的各个版本中的命令空间都有很大的变化.这一点的确有点让人苦恼!在安装WSE时推荐将Visual Studio 

Linux命令环境下基于HTTP协议安全认证的GIT设置

Git 的访问可以采用 HTTP 或 SSH 协议安全的访问,通常我们使用 gitlib 进行 Web 管理,但是在 Linux 命令行开发环境下,基本都是使用 SSH 协议,只需要在 gitlib 里面配置好相应的 SSH Key 就可以. 由于现在开发环境的特殊情况,我们需要在 Linux 命令行开发环境下,不能使用 SSH 方式,而只能使用 HTTP 协议进行安全访问,并且需要对开发者进行认证,并且开发者在本地开发环境中的用户名和密码需要加密存储. 接下来我就简单介绍我们的开发团队是如何在

Win7系统下禁用IPv6协议的方法

  1.首先,单击桌面的windows图标或者是单击屏幕左下角的开始菜单,然后在出现的快捷菜单中进入到控制面板的界面中. 2.之后在控制面板界面中点击进入网络和Internet-网络和共享中心,这样,在新出现的窗口中就可以看到左侧菜单中的更改适配器设置了. 3.单击更改适配器设置,然后在出现的界面中找到正在使用的网络连接并右键点击,选择属性. 4.之后便可以找到列表中的IPv6协议选项了,直接将该项的勾选去掉,然后点击确定保存设置即可.

Apache下部署ssl协议的步骤介绍

https(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的 http 通道,简单讲是 http 的安全版.即 http 下加入 ssl 层,https 的安全基础是 ssl,因此加密的详细内容就需要 ssl. 个人网站用 ssl 证书,国外这几年开始比较流行起来,尤其是 Google 对使用了 ssl 证书的网站收录良好,越来越多的网站开始使用 https 访问了.但是国内的一众搜索引擎对 ssl 就不那么友好