objective-c 编程总结(第九篇)运行时操作 - 序列化
2012-03-14 13:32
387 查看
学习到目前为止,我看到oc实现的序列化方式有两种:NSKeyedArchiver,NSPropertyListSerialization。
在这两种序列化方式中,NSData都是序列化的目标。两种方式的不同点在于NSPropertyListSerialization只是针对字典类型的,而NSKeyedArchiver是针对对象的。(补充一下,在Mac OS环境下,还可以使用NSArchiver获得更加精简的二进制序列化内容,但是NSArchiver在iOS环境下不支持)。
首先讲NSPropertyListSerialization,这个相对简单,只要创建一个NSDictionary,然后调用NSPropertyListSerialization dataFromPropertyList, 将内容写入NSData中就可以了。如果要读入,就调用propertyListFromData.
然后再来看NSKeyedArchiver。从基本的代码示例来看也很简单:
这里要求Person类必须事先了NSCoding协议。NSCoding协议中包含两个必须事先的方法initWithCoder和encodeWithCoder. 参考下面这两个方法的实现:
这里之所以用int age作为序列化属性的示例,是为了引出另一个话题,就是在序列化时对基础类型的处理。NSCoder中是不能存储基础类型的,包括int,float,char *什么的。要将这些进行序列化,必须要进行封装。
一般封装有两种方式。对于数值基本类型,使用Cocoa提供的封装,NSNumber就可以了。对于定长的struct,要分情况,如果struct的所有类型都是定长,并且成员中没有struct类型,那么可以直接使用NSValue来封装;否则,需要自己想办法进行key-value编写。char * 应该直接使用NSString进行封装。
在这两种序列化方式中,NSData都是序列化的目标。两种方式的不同点在于NSPropertyListSerialization只是针对字典类型的,而NSKeyedArchiver是针对对象的。(补充一下,在Mac OS环境下,还可以使用NSArchiver获得更加精简的二进制序列化内容,但是NSArchiver在iOS环境下不支持)。
首先讲NSPropertyListSerialization,这个相对简单,只要创建一个NSDictionary,然后调用NSPropertyListSerialization dataFromPropertyList, 将内容写入NSData中就可以了。如果要读入,就调用propertyListFromData.
NSString * filepath = @”…”;//omitted. NSString * err;//不需要初始化。如果有错误发生,会被复制。 NSDictionary * props = [NSDictionary dictionaryWithObjectsAndKey:@”Lucy”, @"name”, @"Beijing, China”, @"city”, @"supervior”, @"position”, @"Qitiandasheng”, @"company”, nil]; NSData * data = [NSPropertyListSerialization dataFromPropertyList:props format:NSPropertyListXMLFormat_v1_0 errorDescription:&err]; if(!err){ [data writeToFile:filePath atomically:YES];//写入文件 }else{ NSLog(@"error with:%@", err); }
然后再来看NSKeyedArchiver。从基本的代码示例来看也很简单:
Person * lucy = [[Person alloc] initWithName:@"lucy"]; lucy.address = @"Beijing, China"; NSData * data = [NSKeyedArchiver archiveDataWithRootObject:lucy]; [data writeToFile:filePath];
这里要求Person类必须事先了NSCoding协议。NSCoding协议中包含两个必须事先的方法initWithCoder和encodeWithCoder. 参考下面这两个方法的实现:
-(void)encodeWithCoder:(NSCoder *)aCoder{ [aCoder encodingObject:[NSNumber numberWithInt:self.age] forKey @"age"]; } -(id)initWithCoder:(NSCoder*) aDecoder{ if(self=[super init]){ self.age = (int)[(NSNumber*)[aDecoder decodeObjectForKey:@"age"] intValue]; } return self; }
这里之所以用int age作为序列化属性的示例,是为了引出另一个话题,就是在序列化时对基础类型的处理。NSCoder中是不能存储基础类型的,包括int,float,char *什么的。要将这些进行序列化,必须要进行封装。
一般封装有两种方式。对于数值基本类型,使用Cocoa提供的封装,NSNumber就可以了。对于定长的struct,要分情况,如果struct的所有类型都是定长,并且成员中没有struct类型,那么可以直接使用NSValue来封装;否则,需要自己想办法进行key-value编写。char * 应该直接使用NSString进行封装。
相关文章推荐
- objective-c 编程总结(第九篇)运行时操作 - 序列化
- objective-c 编程总结(第七篇)运行时操作 - 动态属性
- objective-c 编程总结(第八篇)运行时操作 - 消息转发
- objective-c 编程总结(第六篇)运行时操作 - 方法交换
- objective-c 编程总结(第八篇)运行时操作 - 消息转发
- objective-c 编程总结(第四篇)日期型类型操作
- objective-c 编程总结(第五篇)集合类型操作
- Objective-C运行时编程指南(Objective-C Runtime Programming Guide)
- objective-c 编程总结(第三篇)内存管理
- VC操作Excel文件编程相关内容总结
- objective-C 编程全解-第08章 类NSObject和运行时系统 中 上
- Objective-C 2.0的运行时编程
- Objective-C 2.0的运行时编程(转)
- Android编程之文件读写操作与技巧总结【经典收藏】
- javaSE基础编程——序列化和反序列化操作(继承Serializable接口)
- 编程swing技巧总结:当在frame中弹出对话框dialog,先完成dialog的操作,才继续往下进行。
- 用VisualStudio2010学习WCF服务编程总结(1)操作重载
- Python之IO编程——文件读写、StringIO/BytesIO、操作文件和目录、序列化
- Objective-C 运行时编程指南 之 Type Encodings
- 001_你使用过Objective-C的运行时编程(Runtime Programming)么?如果使用过,你用它做了什么?你还能记得你所使用的相关的头文件或者某些方法的名称吗?