obj-c编程13:归档
来源:互联网 发布:中国电影进出口数据 编辑:程序博客网 时间:2024/05/16 19:13
这篇归档内容的博文也挺有趣的,笨猫对好玩的东西一向感兴趣啊!如果用过ruby就会知道,obj-c里的归档类似于ruby中的序列化概念,不过从语法的简洁度来说,我只能又一次呵呵了。 下面大家将会看到2种归档数据的方法:属性列表和带键值的编码,前者可以理解为简单的类似字典(比如还有数组)对象的归档,而后者可以实现任意对象的归档化哦。我们依次道来吧。
1. 属性列表(plists)
os x上的程序使用类似字典类概念为支持的XML属性列表(或plists)存储默认参数等配置信息之类的数据,以前“老式”的属性列表数据格式不是XML,现在我们一般都用XML格式啊。属性列表不仅可以是NSDictionary对象,还可以是NSString、NSArray、NSData或是NSNumber类型,可以使用这些类中实现的writeToFile:atomically方法将数据写到文件中去。特别的如果是字典或数组的情况下,保存到文件的格式是XML属性列表格式哦。
#import <Foundation/Foundation.h>#define msg(...) NSLog(__VA_ARGS__)int main(int argc,char *argv[]){@autoreleasepool{NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:\@"val0",@"key0",@"val1",@"key1",@"val2",@"key2",nil];NSDictionary *dict_from_file;//归档if([dict writeToFile:@"data.db" atomically:YES] == NO)msg(@"save to file failed!");//读档dict_from_file = [NSDictionary dictionaryWithContentsOfFile:\@"data.db"];msg(@"%@",dict_from_file);}return 0;}
其中atomically参数是一种保护措施,如果被设为YES,则现将字典内容写入临时备份文件中去,成功后才最终将数据写入指定文件data.db中去。我们看一下返回结果:
apple@kissAir: objc_src$./gd
2014-07-03 15:32:43.263 gd[1991:507] {
key0 = val0;
key1 = val1;
key2 = val2;
}
apple@kissAir: objc_src$cat data.db
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>key0</key>
<string>val0</string>
<key>key1</key>
<string>val1</string>
<key>key2</key>
<string>val2</string>
</dict>
</plist>
很简单,是吧?如果要在跨平台程序中使用属性列表,可以查看一下NSPropertyListSerialization类,使用该类在文件中读写属性列表可以在不同平台之间移植。
2.带键值的编码归档
接下来看一看比简单的属性列表稍微复杂,但也更加通用的带键值的编码归档方法。这就是利用NSKeyedArchiver类创建带键(keyed)的档案来完成,它是从os x 10.2开始支持的哦。在此之前是使用NSArchiver类创建连续的(sequential)归档,这有个不方便的地方:连续归档需要完全按写入时的顺序读取归档中的数据。下面我们来看看,对于简单的字典对象如何归档和读档喽:
#import <Foundation/Foundation.h>#define msg(...) NSLog(__VA_ARGS__)int main(int argc,char *argv[]){@autoreleasepool{NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:\@"val0",@"key0",@"val1",@"key1",@"val2",@"key2",nil];NSDictionary *dict_from_file;//归档if([NSKeyedArchiver archiveRootObject:dict toFile:@"data.archive"] == NO)msg(@"save to file failed!");//读档//dictionaryWithContentsOfFile如果失败会引发异常,这个和以前的返回NO不一样哦。dict_from_file = [NSKeyedUnarchiver unarchiveObjectWithFile:\@"data.archive"];msg(@"%@",dict_from_file);}return 0;}
运行结果如下:
apple@kissAir: objc_src$./gd
2014-07-03 15:47:02.411 gd[2017:507] {
key0 = val0;
key1 = val1;
key2 = val2;
}
apple@kissAir: objc_src$cat data.archive
bplist00?!"X$versionX$objectsY$archiverT$top??$null?
???????Tkey1Tkey0Tkey2Tval1Tval0Tval2?Z$classnameX$classes\NSDictionary? XNSObject_NSKeyedArchiver?#$Troot#-27AGNVahlnprvxz|~???????????????%?
注意如果查看data.archive文档会发现其不是人类可读的文档格式,而是类似于一种二进制格式哦。
上面这些归档和读档方法是很不错,但是想要直接用在我们自己的类中,没门啊!因为编译器不知道我们自己的类以何种表示方式归档呢。所以聪明的童鞋一定猜到了方法,在类中添加自己的归档和读档方法吧!
要归档自己的对象,必须遵守<NSCoding>协议,在类中添加encodeWithCoder和initWithCoder方法,前者用来归档,后者自然是读档啦。下面我们构造2个类Player和Skill类,不同的球员自然有不同的技能啦,比如司令塔,钢铁防线什么的...貌似要跑题啊!STOP!大家直接看代码吧,虽然比较长,但注释钢钢的啊:
#import <Foundation/Foundation.h>#define msg(...) NSLog(__VA_ARGS__)@interface Skill:NSObject <NSCoding>//maybe <NSCoding,NSCopying> :)@property NSString *name;@property int level;-(id)init:(NSString*)name :(int)level;-(NSString*)description;-(void)use;@end@implementation Skill@synthesize name,level;-(id)init:(NSString*)name_v :(int)level_v{self = [super init];if(self){name = name_v;level = level_v;}return self;}-(NSString*)description{return [NSString stringWithFormat:@"[skill:%@ , level:%i]",name,level];}-(void)use{msg(@"%@ is used!!!",self);}-(void)encodeWithCoder:(NSCoder *)encoder{[encoder encodeObject: name forKey:@"Skill#name"];[encoder encodeInt: level forKey:@"Skill#level"];}-(id)initWithCoder:(NSCoder *)decoder{name = [decoder decodeObjectForKey:@"Skill#name"];level = [decoder decodeIntForKey:@"Skill#level"];return self;}@end@interface Player:NSObject <NSCoding>@property NSString *name;@property int number;@property NSMutableArray *skills;-(NSString*)description;@end@implementation Player@synthesize name,number,skills;-(id)init{//需要为skills对象分配空间啊!否者skills打印的是NULLself = [super init];if(self){skills = [[NSMutableArray alloc] init];}return self;}-(NSString*)description{return [NSString stringWithFormat:@"[%@:NO.%i] skills:\n%@",\name,number,skills];}-(void)encodeWithCoder:(NSCoder *)encoder{[encoder encodeObject: name forKey:@"Player#name"];[encoder encodeInt: number forKey:@"Player#number"];[encoder encodeObject: skills forKey:@"Player#skills"];}-(id)initWithCoder:(NSCoder *)decoder{name = [decoder decodeObjectForKey:@"Player#name"];number = [decoder decodeIntForKey:@"Player#number"];skills = [decoder decodeObjectForKey:@"Player#skills"];return self;}@endint main(int argc,char *argv[]){@autoreleasepool{Player *p0 = [[Player alloc] init];Skill *s0 = [[Skill alloc] init:@"super_lead" :3];//司令塔Skill *s1 = [[Skill alloc] init:@"steel_defend" :2];//钢铁防守Skill *s2 = [[Skill alloc] init:@"steal_master" :2];//抢断大师Skill *s3 = [[Skill alloc] init:@"spiritual_leader" :1];//精神领袖p0.name = @"messi";p0.number = 10;//利用数组的addObject方法加入每个技能[p0.skills addObject:s0];[p0.skills addObject:s1];[p0.skills addObject:s2];[p0.skills addObject:s3];msg(@"%@",p0);//像单个对象那样归档吧if([NSKeyedArchiver archiveRootObject:p0 toFile:@"player.arch"] == NO)msg(@"save to archiving failed!");//像单个对象那样读档吧Player *p1 = [NSKeyedUnarchiver unarchiveObjectWithFile:@"player.arch"];msg(@"%@",p1);}return 0;}例子比较长,但很简单哦,运行结果如下:
apple@kissAir: objc_src$./gd
2014-07-03 17:00:15.623 gd[2260:507] [messi:NO.10] skills:
(
"[skill:super_lead , level:3]",
"[skill:steel_defend , level:2]",
"[skill:steal_master , level:2]",
"[skill:spiritual_leader , level:1]"
)
2014-07-03 17:00:15.626 gd[2260:507] [messi:NO.10] skills:
(
"[skill:super_lead , level:3]",
"[skill:steel_defend , level:2]",
"[skill:steal_master , level:2]",
"[skill:spiritual_leader , level:1]"
)
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:\@"val0",@"key0",@"val1",@"key1",@"val2",@"key2",nil];NSMutableData *buf = [NSMutableData data];NSKeyedArchiver *arch = [[NSKeyedArchiver alloc] \initForWritingWithMutableData: buf];//将Player对象和字典对象一起归档[arch encodeObject:p0 forKey:@"Player"];[arch encodeObject:dict forKey:@"Dict"];//结束在buf中添加对象,我称之为“封口”[arch finishEncoding];//归档写入文件if([buf writeToFile: @"mobjs.arch" atomically:YES] == NO){msg(@"arch to file failed!");return 1;}//将Player对象和字典对象一起读档(解档)NSData *buf_read = [NSData dataWithContentsOfFile:@"mobjs.arch"];if(!buf_read){msg(@"read file : mobjs.arch failed!");return 2;}NSKeyedUnarchiver *unarch = [[NSKeyedUnarchiver alloc] \initForReadingWithData: buf_read];Player *p2 = [unarch decodeObjectForKey:@"Player"];NSDictionary *dict1 = [unarch decodeObjectForKey:@"Dict"];//别忘了也要完成一下哦[unarch finishDecoding];msg(@"dict:%@",dict1);msg(@"player:%@",p2);
2014-07-03 17:34:23.090 gd[2362:507] dict:{
key0 = val0;
key1 = val1;
key2 = val2;
}
2014-07-03 17:34:23.091 gd[2362:507] player:[messi:NO.10] skills:
(
"[skill:super_lead , level:3]",
"[skill:steel_defend , level:2]",
"[skill:steal_master , level:2]",
"[skill:spiritual_leader , level:1]"
)
#import <Foundation/Foundation.h>#define msg(...) NSLog(__VA_ARGS__)#define mstr(x) [NSMutableString stringWithString:x]int main(int argc,char *argv[]){@autoreleasepool{NSData *buf;NSMutableArray *ary1 = [NSMutableArray arrayWithObjects:\mstr(@"one"),mstr(@"two"),mstr(@"three"),nil];NSMutableArray *ary2;NSMutableString *mstr;//使用归档进行深拷贝,没有实际读取文件,走的是内存路线啊!buf = [NSKeyedArchiver archivedDataWithRootObject: ary1];ary2 = [NSKeyedUnarchiver unarchiveObjectWithData: buf];mstr = [ary2 objectAtIndex:0];[mstr appendString:@"_fixed"];msg(@"%@\n****************************%@",ary1,ary2);}return 0;}
apple@kissAir: objc_src$./6
2014-07-03 17:45:58.972 6[2414:507] (
one,
two,
three
)
****************************(
"one_fixed",
two,
three
)
- obj-c编程13:归档
- obj-c编程15[Cocoa实例03]:MVC以及归档化示例
- obj-c编程04:类的继承
- obj-c编程07:异常处理
- obj-c编程08:分类和协议
- obj-c编程09:块的语法
- obj-c编程12:复制对象
- obj-c编程16:键值编码(KVC)
- obj-c编程17:键值观察(KVO)
- obj-c编程19:关联对象
- obj-c编程06:反射与元编程初步
- Objective-C 编程语言(13)远程消息---Obj-C 对远程消息的支持(同步异步消息)
- Objective-C 编程语言(13)远程消息---Obj-C 对远程消息的支持(指针参数、代理和拷贝)
- obj-c编程02:给类自动合成存取方法
- obj-c编程03:多个参数方法的定义
- obj-c编程14:Cocoa和Cocoa Touch简介
- obj-c编程18:多对多的观察者模式
- !!!Obj-c on Mac --- Chapter 13 Protocols
- 碳腔杏氯乃矫撞狈晌芳铰诵剂铺俅
- 肆沧铰狈诘燎蒙卧纳姓都氯卜众芳
- 淖遗盏馅什抡戏檀狙盎懊判仿纯淖
- 诶涤拖箍再妇虑鸵淤市诖磕铰潘星
- [Leetcode]Palindrome Number & reverse integer
- obj-c编程13:归档
- 逊劣雌短仑成史锤胶至回遣透鸭至
- 面试记录
- Android学习笔记3-界面
- 鬃壤赫簇艺沮猎匮推饺勤偈慰压踊
- GIT on solaris
- linux内核API----内存管理(-)
- 傺揽厮安巧蓉溉唤非绷非菏怨亲奖
- 颓澜岸载痘钡粕姓艘卧方彻陀箍任