读书人

objective-c中的本地化操作(序列化

发布时间: 2013-11-02 19:41:10 作者: rapoo

objective-c中的本地化操作(序列化,归档)(十二)

holydancer原创,如需转载,请在显要位置注明:

转自holydancer的CSDN专栏,原文地址:http://blog.csdn.net/holydancer/article/details/7371643

?

先介绍一个自定义类描述的方法description,一般情况下,一个自定义类我们在用%@输出的时候,给出的是一个内存地址,我们在该类的.m文件里重写description方法,来修改输出内容,呆会儿我们要用到这个方法来验证今天学习内容,所以先看一段代码熟悉一下:

Human.h:

?

[plain]?view plaincopy?
  1. #import?<Foundation/Foundation.h>??
  2. ??
  3. @interface?Human?:?NSObject??
  4. {??
  5. ????int?age;??
  6. ????NSString?*name;??
  7. ????Human?*child;??
  8. }??
  9. ??
  10. @property?int?age;??
  11. @property?(copy)NSString?*name;??
  12. @property?(retain)Human?*child;??
  13. @end??


Human.m:

?

?

[plain]?view plaincopy?
  1. #import?"Human.h"??
  2. ??
  3. @implementation?Human??
  4. @synthesize?age;??
  5. @synthesize?name;??
  6. @synthesize?child;??
  7. ??
  8. //-(NSString?*)description??
  9. //{??
  10. //????NSString?*des?=?[NSString?stringWithFormat:@"%d,%@,%@",age,name,child];??
  11. //????return?des;??
  12. //}??
  13. ??
  14. @end??


上面的重写描述被注释掉了,我们先看未修改前的输出:

?

main.m:

?

[plain]?view plaincopy?
  1. #import?<Foundation/Foundation.h>??
  2. #import?"Human.h"??
  3. ??
  4. int?main(int?argc,?const?char?*?argv[])??
  5. {??
  6. ??
  7. ????@autoreleasepool?{??
  8. ????????Human?*human1=[[Human?alloc]init];??
  9. ????????Human?*human2=[[Human?alloc]init];??
  10. ????????human1.child=human2;??
  11. ????????human1.name=@"holydancer";??
  12. ????????human1.age=22;??
  13. ????????NSLog(@"%@",human1);??
  14. ??????????????
  15. ????}??
  16. ????return?0;??
  17. }??

?

?

2012-03-20 08:47:32.980 category[304:403] <Human: 0x7ff2cb414380>

?

如果把human.m中的注释去掉的话输出结果如下:

?

2012-03-20 08:48:09.869 category[315:403] 22,holydancer,0,(null),(null)

?

很简单吧,这样就可以查看自己定义类的内容了,好了,下面就让我们来研究一下在objective-c中如何实现序列化。

在OC中,有四类对象是可以直接使用writeToFile方法将内容写入磁盘的,分别是NSString,NSArray,NSDictionary,NSData.看代码:

?

[plain]?view plaincopy?
  1. #import?<Foundation/Foundation.h>??
  2. #import?"Human.h"??
  3. ??
  4. int?main(int?argc,?const?char?*?argv[])??
  5. {??
  6. ??
  7. ????@autoreleasepool?{??
  8. ??????
  9. ????????NSData?*data=[[NSData?alloc]init];??
  10. ????????NSString?*string=[[NSString?alloc]init];??
  11. ????????NSArray?*array=[[NSArray?alloc]init];??
  12. ????????NSDictionary?*dictionary=[[NSDictionary?alloc]init];??
  13. ??????????????????
  14. ????????[data?writeToFile:@"/Users/holydancer/Desktop/text1.txt"?atomically:YES];??
  15. ????????[string?writeToFile:@"/Users/holydancer/Desktop/text2.txt"?atomically:YES];??
  16. ????????[array?writeToFile:@"/Users/holydancer/Desktop/text3.txt"?atomically:YES];??
  17. ????????[dictionary?writeToFile:@"/Users/holydancer/Desktop/text4.txt"?atomically:YES];??
  18. ????????//atomically参数是指是否将写入文件的内容开启保护机制,如果开启,会在复制时创建临时文件进行复制,以免写入失败破坏原始文件。安全,但是会消耗内存。??
  19. ????????//上面的文件地址,如果不存在的话会自动生成。有的话会覆盖原有文件内容。??????
  20. ????}??
  21. ????return?0;??
  22. }??



?

objective-c中的本地化操作(序列化,存档)(十二)

以上四种是COCOA自带可以写入磁盘文件的类型,但是我们常常用到自定义类,可是里面并没有writeToFile方法,怎么办呢?这时NSData的作用就体现出来了,我们可以把任意自定义类转化成NSData格式即可,这个过程我们称之为编码,或者archive归档,需要将自定义类实现NSCoding协议并重写encodeWithCoder和initWithCoder两个方法,分别用以编码和反编码。然后在编码时会用NSCoder的子类NSKeyedArchiver和NSKeyedUnarchiver分别调用archivedDataWithRootObject和unarchiveObjectWithData来启动自定义类中重写的那两个方法,类似于回调。看代码:

Human.h:

?

[plain]?view plaincopy?
  1. #import?<Foundation/Foundation.h>??
  2. ??
  3. @interface?Human?:?NSObject<NSCoding>??
  4. {??
  5. ????int?age;??
  6. ????NSString?*name;??
  7. ????Human?*child;??
  8. }??
  9. ??
  10. @property?int?age;??
  11. @property?(copy)NSString?*name;??
  12. @property?(retain)Human?*child;??
  13. @end??


Human.m:

?

?

[plain]?view plaincopy?
  1. #import?"Human.h"??
  2. ??
  3. @implementation?Human??
  4. @synthesize?age;??
  5. @synthesize?name;??
  6. @synthesize?child;??
  7. ??
  8. -(NSString?*)description??
  9. {??
  10. ????NSString?*des?=?[NSString?stringWithFormat:@"%d,%@,%@",age,name,child];??
  11. ????return?des;??
  12. }??
  13. -(void)encodeWithCoder:(NSCoder?*)aCoder//要一一对应??
  14. {??
  15. ????[aCoder?encodeInt:age?forKey:@"age"];??
  16. ????[aCoder?encodeObject:name?forKey:@"name"];??
  17. ????[aCoder?encodeObject:child?forKey:@"child"];??
  18. }??
  19. -(id)initWithCoder:(NSCoder?*)aDecoder//和上面对应??
  20. {??
  21. ????if?(self=[super?init])?{??
  22. ????????self.age=[aDecoder?decodeIntForKey:@"age"];??
  23. ????????self.name=[aDecoder?decodeObjectForKey:@"name"];??
  24. ????????self.child=[aDecoder?decodeObjectForKey:@"child"];??
  25. ????}??
  26. ????return?self;??
  27. }??
  28. @end??


main.m:

?

?

[plain]?view plaincopy?
  1. #import?<Foundation/Foundation.h>??
  2. #import?"Human.h"??
  3. #import?<Foundation/NSKeyedArchiver.h>??
  4. ??
  5. int?main(int?argc,?const?char?*?argv[])??
  6. {??
  7. ??
  8. ????@autoreleasepool?{??
  9. ??????
  10. ????????Human?*human1=[[Human?alloc]init];??
  11. ????????Human?*human2=[[Human?alloc]init];??
  12. ????????human1.age=20;??
  13. ????????human1.name=@"holydancer";??
  14. ????????human1.child=human2;??
  15. ????????//定义好自定义对象后使用NSCoding的子类调用archivedDataWithRootObject方法进行archive??
  16. ????????NSData?*data1=[NSKeyedArchiver?archivedDataWithRootObject:human1];??
  17. ????????//转成NSData类型后就可以写入本地磁盘了??
  18. ????????[data1?writeToFile:@"/Users/holydancer/Desktop/tmp.txt"?atomically:YES];??
  19. ????????//倒过来的话先读取磁盘文件??
  20. ????????NSData?*data2=[NSData?dataWithContentsOfFile:@"/Users/holydancer/Desktop/tmp.txt"];??
  21. ????????Human?*human3=[NSKeyedUnarchiver?unarchiveObjectWithData:data2];??
  22. ????????NSLog(@"%@,%@",human1,human3);??
  23. ????}??
  24. ????return?0;??
  25. }??

?

?

2012-03-20 10:10:29.871 category[458:403]?

20,holydancer,0,(null),(null)

20,holydancer,0,(null),(null)

有的同学一直不太清楚NSKeyedArchiver和NSKeyedUnarchiver是什么,调用的又是什么方法,大家可以在头文件里找到这样的信息:

objective-c中的本地化操作(序列化,存档)(十二)

可以发现,NSKeyedArchiver是NSCoder的子类,而archivedDataWithRootObject是里面的一个类方法,这时我们看到archivedDataWithRootObject方法下在还有一个方法,不错,这个方法可以直接将自定义类写入本地磁盘,所以上在的代码我们还可以这样写:

?

[plain]?view plaincopy?
  1. #import?<Foundation/Foundation.h>??
  2. #import?"Human.h"??
  3. #import?<Foundation/NSKeyedArchiver.h>??
  4. ??
  5. int?main(int?argc,?const?char?*?argv[])??
  6. {??
  7. ??
  8. ????@autoreleasepool?{??
  9. ??????
  10. ????????Human?*human1=[[Human?alloc]init];??
  11. ????????Human?*human2=[[Human?alloc]init];??
  12. ????????human1.age=20;??
  13. ????????human1.name=@"holydancer";??
  14. ????????human1.child=human2;??
  15. ????????[NSKeyedArchiver?archiveRootObject:human1?toFile:@"/Users/holydancer/Desktop/tmp.txt"];//直接写入磁盘??
  16. ????????Human?*human3=[NSKeyedUnarchiver?unarchiveObjectWithFile:@"/Users/holydancer/Desktop/tmp.txt"];//从磁盘直接读取为id类型??
  17. ????????NSLog(@"\n%@\n%@",human1,human3);??
  18. ????}??
  19. ????return?0;??
  20. }??



?

2012-03-20 10:16:43.561 category[475:403]?

20,holydancer,0,(null),(null)

20,holydancer,0,(null),(null)

最后,不得不说说cocoa中的方法命名,一个一个方法长得,虽然很人性化很好记,不过敲起来真是麻烦啊。

?

关键字:objective-c ,objective c , oc ,本地化,序列化,归档,archive ,NSCoder ,NSCoding , NSKeyedArchiver ,NSKeyedUnarchiver

读书人网 >移动开发

热点推荐