美文网首页
oc归档与解档(序列化和反序列化)

oc归档与解档(序列化和反序列化)

作者: 西门淋雨 | 来源:发表于2017-11-25 14:42 被阅读67次

    Foundation框架的归档功能

    将对象存储转换为二进制序列的过程成为归档、打包或编码,逆变换称为解档、解码或对象还原。

    可以使用NSKeyedArchiver和NSKeyedUnarchiver完成对象的归档和解档操作,而他们都是抽象类NSCoder的子类。

    所有可以归档的对象都必须要适用于协议NSCoding。协议NSCoding在Foundation/NSObject.h中定义,NSObject自身并不采用该协议。NSString、NSDictionary等Foundation框架的主要类都适用协议NSCoding。

    协议NSCoding按照如下方式声明:

    @protocolNSCoding

    -(void)encodeWithCoder:(NSCoder*)coder

    -(id)initWithCoder:(NSCoder*)coder

    归档方法的定义

    协议NSCoding中,函数encodeWithCoder:定义了归档自身的方法。

    - (void)encodeWithCoder:(NSCoder *)coder

    {

        [super encodeWithCoder:coder];

        //超类需要适用NSCoding协议

        [coder encodeObject:对象 forKey:关键词字符串];

        [coder encodeInt:实数变量 forKey:关键词字符串];

    }

    如果超类不适用协议NSCoding,则不能调用encodeWithCoder:方法。

    类自身对包含的实例变量归档。在类没有自己的实例变量且超类中定义了方法encodeWithCoder:的情况下,该方法就不需要在定义了。

    通过使用NSString字符串作为键值,可以指定归档解档的内容。让某个类实例归档时,它的实例变量必须指定成不同的键值。在单个对象内部,如果超类使用了一个键值,那么子类中就不能使用该键值。键值只需在同一个类内区分出来即可,不同的类可使用相同的键值。

    当对象图有闭环时,同一个对象会重复要求归档,实际上已归档的对象是不用重复归档的。

    解档方法的定义

    - (instancetype)initWithCoder:(NSCoder *)coder{

        self= [superinitWithCoder:coder];

        //超类不适应于协议NSCoding时,    

        //建议使用 self = [super init];

    if (self) {

        self.name= [coder decodeObjectForKey: 键值];

        self.age= [coder decodeIntForKey: 键值];   

         }

        returnself;

    }

    归档示例程序:

    main.m

    #import  <Foundation/Foundation.h>

    #import"Person.h"

    int main(intargc,constchar* argv[]) {    

        @autoreleasepool {        

            Person * p = [[Person alloc] init];       

             p.name= @"lu";       

             p.age=18;       

             p.weight=100.0;

            BOOLisSuccess = [NSKeyedArchiver archiveRootObject:p toFile:@"/Users/lu/Desktop/test.plist"];if(isSuccess) {NSLog(@"归档成功");     

               }else{

                    NSLog(@"归档失败");      

              }  

          }

        return0;

    }

    解档示例程序:

    main.m

    intmain(intargc,constchar* argv[]) {    

        @autoreleasepool {

                //解档    

                Person * p = [NSKeyedUnarchiver unarchiveObjectWithFile:@"/Users/lu/Desktop/test.plist"];

                NSLog(@"%@",p.name);

                NSLog(@"%d",p.age);

                NSLog(@"%f",p.weight);    

            }

            return0;

    }

    若类中实例变量为其他类对象,则还需要在其他类中实现encodeWithCoder:和initWithCoder:方法。

    示例程序:

    Dog.m

    #import"Dog.h" 

    @implementation Dog

    - (void)encodeWithCoder:(NSCoder *)coder{ 

         [coder encodeObject:self.nameforKey:@"name"];   

         [coder encodeInt:self.ageforKey:@"age"];}

    - (instancetype)initWithCoder:(NSCoder *)coder{

        self= [superinit];

        if (self) {

            self.name= [coder decodeObjectForKey:@"name"];self.age= [coder decodeIntForKey:@"age"];    }

            return self;

    }

    @end

    student.m

    #import"Student.h"

    #import"Dog.h"

    @implementationStudent

    //归档

    - (void)encodeWithCoder:(NSCoder *)coder{  

     [coder encodeObject:self.nameforKey:@"name"];   

     [coder encodeInt:self.scoreforKey:@"score"];  

     [coder encodeInt:self.numberforKey:@"number"]; 

      [coder encodeObject:self.dogforKey:@"dog"];}

    //解档

    - (instancetype)initWithCoder:(NSCoder *)coder{

    self = [superinit];

        if (self) {

        self.name= [coder decodeObjectForKey:@"name"];

        self.score= [coder decodeIntForKey:@"score"];

        self.number= [coder decodeIntForKey:@"number"];

        self.dog= [coder decodeObjectForKey:@"dog"];  

      }

        return self;

    }

    @end

    main.m

    int main(intargc,constchar* argv[]) { 

       @autoreleasepool {      

         Student * stu = [[Student alloc] init];        

        stu.name= @"di";       

         stu.score=70;       

         stu.number=20;      

          Dog * d = [[Dog alloc] init];       

         d.name= @"Chen";     

          d.age=10;      

          stu.dog= d;

    //归档

    BOOL isSuccess = [NSKeyedArchiver archiveRootObject:stu toFile:@"/Users/lu/Desktop/Stu.txt"];if(isSuccess) {NSLog(@"Yes");     

       }else{

            NSLog(@"NO");    

        }

    //解档

        Student * stu3 = [NSKeyedUnarchiver unarchiveObjectWithFile:@"/Users/lu/Desktop/Stu.txt"];NSLog(@"%@", stu3.name);

        NSLog(@"%d", stu3.score);

        NSLog(@"%d", stu3.number);

        NSLog(@"%@", stu3.dog.name);

        NSLog(@"%d", stu3.dog.age);  

          }

        return0; 

     }

    对多个对象进行归档,可以先将多个对象存储于NSArray、NSMutableArray、NSDictionary或NSMutableDictionary中,再进行归档。

    示例程序:

    NSArray* stuArray = @[stu, stu1, stu2];

    BOOLisSuccess = [NSKeyedArchiver archiveRootObject:stuArray toFile:@"/Users/lu/Desktop/stuArray.txt"];

    if(isSuccess) {

        NSLog(@"Yes");        

    }else{

        NSLog(@"NO");        

    }

    最后一种方式利用NSData对多个对象进行归档解档

    示例程序

    main.m

    #import

    #import"Person.h"

    int main(intargc,constchar* argv[]) {  

      @autoreleasepool {       

         Person * p = [[Person alloc] init];    

         p.name= @"dou";  

         p.age=22;    

         p.weight=120.00;   

         Person * p2 = [[Person alloc] init]; 

          p2.name= @"dashu";  

          p2.age=24;  

          p2.weight=140.3;  

          NSMutableData * data = [NSMutableData data];//        根据二进制流创建NSkeyedArchiver对象    

          NSKeyedArchiver * archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];

    //        对对象进行归档操作

        [archiver encodeObject:p forKey:@"person1"];    

         [archiver encodeObject:p2 forKey:@"person2"];

    //        结束归档

    /*** -[NSKeyedArchiver dealloc]: warning: NSKeyedArchiver deallocated without having had -finishEncoding called on it.

    归档如果没有结束 finishEncoding就不会归档成功,产生文件无法打开    The data couldn't be read because it isn't in the correct format.

    */

    [archiver finishEncoding];

    BOOL isSuccess = [data writeToFile:@"/Users/lu/Desktop/Data.plist"atomically:YES];if(isSuccess) {

           NSLog(@"归档成功!");   

         }else{

            NSLog(@"归档失败");      

      }

    //解档NSData * data = [NSData dataWithContentsOfFile:@"/Users/lu/Desktop/Data.plist"];        NSKeyedUnarchiver * unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];      

      Person * p = [unarchiver decodeObjectForKey:@"person1"];     

      Person * p2 = [unarchiver decodeObjectForKey:@"person2"];

    //结束解档 解档没有finishDecoding无影响

    // [unarchiver finishDecoding];

    NSLog(@"%@", p.name);

    NSLog(@"%d", p.age);NSLog(@"%f", p.weight);

    NSLog(@"%@", p2.name);NSLog(@"%d", p2.age);NSLog(@"%f", p2.weight);   

     }

    return0;

    }

    相关文章

      网友评论

          本文标题:oc归档与解档(序列化和反序列化)

          本文链接:https://www.haomeiwen.com/subject/iprcbxtx.html