OC中的归档和反归档

时间:2022-02-15 16:21:31

所谓的归档和反归档也就是我们将数据存储到文件中,和从文件中获取数据,和字符串数组不同的是对象的归档是比较复杂的这个地方我们就通过一个例子来演示一下怎样在OC中实现归档和反归档。

首先我们要做的是是创建一个对象,通过创建对象,并且将对象存入到数组中,然后在将数组写到文件上,那么这一系列的操作我们该怎样的完成这些操作,下面我们就进入我们的例子来解释怎样归档和反归档:

首先的是我们需要创建一个对象:

#import <Foundation/Foundation.h>
@interface Person : NSObject
@property(nonatomic,copy) NSString *pname;
@property(nonatomic,assign) int age;
-(instancetype)initWithPname:(NSString *)pname andage:(int)age;
+(instancetype)personWithinit:(NSString *)pname andage:(int)age;
@end
//我们创建一个类并且定义的构造函数,和类的构造函数。

然后我们要写实现文件:

#import "Person.h"
@implementation Person
-(instancetype)initWithPname:(NSString*)pname andage:(int)age
{
    if([super init])
    {
        _pname=pname;
        _age=age;
    }
    return  self;
}
+(instancetype)personWithinit:(NSString*)pname andage:(int)age
{
    return [[self alloc] initWithPname:pname andage:age];
}
-(NSString *)description
{
    return [NSString stringWithFormat:@"name=%@,age=%d",_pname,_age];

}
-(void)encodeWithCoder:(NSCoder *)aCoder{
    [aCoder encodeObject:self.pname forKey:@"pname"];
    [aCoder encodeObject:[NSNumber numberWithInt:self.age] forKey:@"age"];
    
}
-(id)initWithCoder:(NSCoder *)aDecoder
{
    if(self=[super init])
    {
         self.pname=[aDecoder decodeObjectForKey:@"pname"];
        [self setAge:[[aDecoder decodeObjectForKey:@"age"] intValue]];
    }
    return self;
}
@end

我们在定义类的时候,我们仅仅声明了两个函数,但是我们在该类的实现文件中去实现了四个函数,很明显,有两个函数是重写的,我们为什么要重写这些函数,重写这些函数有什么作用,都是我们要问的问题。

接着我们来看主函数:

#import "Person.h"
#import <Foundation/Foundation.h>
NSString *file=@"/Users/gemfortest/Desktop/123.plist";
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSMutableArray *arr=[NSMutableArray arrayWithCapacity:5];
         Person *p1=[Person personWithinit:@"xiaoming" andage:5];
         Person *p2=[Person personWithinit:@"daming" andage:6];
         Person *p3=[Person personWithinit:@"zhongming" andage:7];
         Person *p4=[Person personWithinit:@"wangming" andage:8];
        [arr addObject:p1];
        [arr addObject:p2];
        [arr addObject:p3];
        [arr addObject:p4];
        for(Person *p5 in arr)
        {
            NSLog(@"%@",p5);
         }
        //归档之前是首先定义一个字字符串,这个字符串是指向一个位置
        [NSKeyedArchiver archiveRootObject:arr toFile:file];
        NSMutableArray *Arr1;
        Arr1=[NSKeyedUnarchiver unarchiveObjectWithFile:file];
        for(Person *p6 in Arr1)
        {
            printf("-----------");
            NSLog(@"%@",p6);
        }
     }
    return 0;
}

到现在为止我们似乎还没有进入正题,我们看看主函数中,明确的写出了我们归档和反归档的步骤:

第一步:我们要将数据写入到某一个文件中,当然要做的是给出文件一个路径,于是我们在开始的时候定义了这样的一个字符:NSString *file=@"/Users/gemfortest/Desktop/123.plist";

第二步:将数组写入到文档:[NSKeyedArchiver archiveRootObject:arr toFile:file];需要注意的是我们写入文档的编码和我们在屏幕上看到的代码是不一样的,也就是说我们在对象写入到文件中之前我们需要做的是进行将对象进行编码,其实是对对象中的每一个成员变量进行编码,这个也是我们为什么要在类的实现文件中重写两个函数,当我们将对象写入到文件的时候,其实是写入的id,对象会自动的调用函数:

-(void)encodeWithCoder:(NSCoder *)aCoder{
    [aCoder encodeObject:self.pname forKey:@"pname"];
    [aCoder encodeObject:[NSNumber numberWithInt:self.age] forKey:@"age"];
    
}
,这样我们也就将对象的 数据写入到了文件上。

第三步:反归档并且从文件中获取对象数据并且遍历

       NSMutableArray *Arr1;
        Arr1=[NSKeyedUnarchiver unarchiveObjectWithFile:file];
        for(Person *p6 in Arr1)
        {
            printf("-----------");
            NSLog(@"%@",p6);
        }

其实反归档是我们将文档中的 数据编码格式也要转化为在屏幕上能显示的编码的格式,于是我们要调用一个函数:

-(id)initWithCoder:(NSCoder *)aDecoder
{
    if(self=[super init])
    {
         self.pname=[aDecoder decodeObjectForKey:@"pname"];
        [self setAge:[[aDecoder decodeObjectForKey:@"age"] intValue]];
    }
    return self;
}
这个函数是在反归档的时候自动的调用的。因为我们归档的时候向文件中写入的是一个数组,所以返回的也是一个数组。

最后遍历也就不多说了。