归档自定义对象
Cocoa中,归档数据到文件,使用NSKeyedArchiver的archiveRootObject:toFile:方法。对于一般的数据类型(例如字符串),这个步骤是非常简单的。Apple官方文档中,这些数据类型包括:NSDataNSStringNSNumberNSDateNSArrayNSDictionary很显然,复杂数据例如UIImage,无法直接归档。但我们有一种变通的做法,先将UIImage对象转换为NSData,再对NSData进行归档。www.zzzyk.com注1:准确地说,这依赖于iOS的版本。在iOS4中,UIImage未实现NSCoding协议,在iOS5中,UIImage实现了NSCoding协议。对于自定义的类型,我们也可以参考这一做法,即先将将自定义类型转换为NSData,再对NSData进行归档。问题在于,NSKeyedArchiver在归档一个自定义对象时,怎么知道如何将一个自定义对象编码为一个NSData?而且,当我们从文件中反归档时,NSKeyedUnarchiver怎么知道将NSData转变为一个自定义对象?这就是NSCoding 协议需要解决的问题。实际上,NSCoding协议规定的两个方法,分别用于解决这两个问题。当NSKeyedArchiver 在归档一个对象时,将调用对象的encodeWithCoder:方法,用于将对象转换为NSData(或NSString等其他5种类型);而NSKeyedUnarchiver在反归档一个对象时,则调用对象的initWithCoder:方法,用于将NSData(或NSString等其他5种类型)转换为指定的对象类型。上述6种类型(NSData、NSString等)在归档/反归档时显得尤其简单,是因为苹果已经为我们实现了NSCoding协议。而自定义对象不同,需要程序员自己实现其NSCoding协议。新建项目,创建一个类MyClass,在头文件中声明对NSCoding协议的实现。然后为他设计属性如下:@inte易做图ce MyClass : NSObject<NSCoding>@property(strong,nonatomic)NSString* name;@property(assign,nonatomic)int age;@property(assign,nonatomic)BOOL 易做图;@end然后,在实现中实现NSCoding协议:@implementation MyClass@synthesize name,age,易做图;-(void)encodeWithCoder:(NSCoder *)encoder{[encoderencodeObject:self.name forKey:@"name"];[encoderencodeObject:[NSNumber numberWithInt: self.age] forKey:@"age"];[encoderencodeObject:[NSNumber numberWithBool: self.易做图] forKey:@"易做图"];}- (id)initWithCoder:(NSCoder *)decoder {if (self = [superinit]) {self.name = [decoder decodeObjectForKey:@"name"];self.age =((NSNumber*)[decoderdecodeObjectForKey:@"age"]).intValue;self.易做图 =((NSNumber*) [decoderdecodeObjectForKey:@"易做图"]).boolValue;}return self;}@end在encodeWithCoder:方法中,这两句好像显得有点多余:[encoder encodeObject:[NSNumber numberWithInt: self.age]forKey:@"age"];[encoder encodeObject:[NSNumber numberWithBool: self.易做图]forKey:@"易做图"];然而事实并不是这样的,encoder对象只能对已经实现了NSCoding的对象进行编码(即转换为6种类型之一),对于int、BOOL这样的简单类型则不行。因此,我们需要对age和易做图属性转换为其他类型(6种类型之一),比如NSNumber。同样,在initWithCoder:方法中,我们必须对decoder反编码后的数据进行必要的转换,将它们由NSNumber(因为编码时我们是用NSNumber存储的)转换为相应属性原来的类型,才能进行赋值:self.age =((NSNumber*)[decoderdecodeObjectForKey:@"age"]).intValue;self.易做图 =((NSNumber*) [decoder decodeObjectForKey:@"易做图"]).boolValue;接下来,我们使用NSKeyedArchiver/NSKeyedUnarchiver来对MyClass进行归档/反归档。打开ViewController.xib,设计如下UI界面:使用Asistant Editor,创建必要的连接。这时ViewController.h文件内容将显示如下:#import "MyClass.h"#define AppDocuments [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES) objectAtIndex:0]@inte易做图ce ViewController : UIViewController<UITextFieldDelegate>@property (retain, nonatomic) IBOutlet UITextField *tfName;@property (retain, nonatomic) IBOutlet UITextField *tfAge;@property (retain, nonatomic) IBOutlet UISegmentedControl *segSex;@property (retain, nonatomic) IBOutlet UIButton *button;- (IBAction)archiveUnarchive:(id)sender;@end在ViewDidLoad方法中,加入语句[self initUI:nil];其中,initUI:方法定义如下:-(void)initUI:(MyClass*)obj{if (obj==nil) {tfName.text=nil;tfAge.text=nil;segSex.selectedSegmentIndex=0;}else{tfName.text=obj.name;tfAge.text=[NSString stringWithFormat:@"%d",obj.age];segSex.selectedSegmentIndex=obj.易做图;}}定义方法makeMyClassInstance,在这个方法中我们通过用户在界面是输入的内容创建MyClass实例:-(MyClass*)makeMyClassInstance{MyClass*obj=[[MyClass alloc]init];obj.name=tfName.text;obj.age=[tfAge.textintValue];obj.易做图=[segSexselectedSegmentIndex]!=0;return [objautorelease];}定义按钮事件的Action方法如下:- (IBAction)archiveUnarchive:(id)sender {button.enabled=NO;NSString*filePath=[AppDocuments stringByAppendingPathComponent:@"customobject.txt"];if(button.tag==0) {if (tfName && tfName.text.length>0 && tfAge&& tfAge.text.length>0) {button.tag=1;[button setTitle:@"反归档" forState:UIControlStateNormal];My补充:移动开发 , IOS ,
上一个:IOS手势操作:点击+滑动
下一个:ios 常用工具类
- 更多wap疑问解答:
- 新人求助QPainter
- 为什么程序都退出了还可以收到推送?如果大多设备都可以推送那运营商怎么办?
- qt 4.7 sqlserver2000 存储过程调用
- 关于ANDROID4.0.1编译问题!
- Android FrameBuffer读屏幕30秒后mmap失败
- 联通粗定位用java程序如何来请求和接受数据
- 为什么QT运行Android平台的程序时,mouseMoveEvent事件响应的间隔时间很长??????????
- android与PC蓝牙通讯
- 指定大小的label 内容可变,如果内容超出label的宽度,将未能显示的部分显示在另一个label上
- Android调试
- android如何通过wifi连接无线打印机
- 运行程序,release目录下产生一个乱码文件夹
- 分享个某机构最新安卓资料,自己验证了
- service启动不起来,掉不了service connection
- 求助:QT5.0 没有QPrinter吗