iOS之对象归档

#import "ViewController.h"
#import "KFApple.h"

@interface ViewController ()
@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];

    /*
     对象归档
     所谓对象归档,就是类似于其他语言中的“序列化”机制,归档就是用某种格式把一个或多个对象保存到指定文件中,方便以后文件中恢复它们。通常来说,归档包含两方面的操作;一方面需要把对象写入指定文件中,另一方面需要从文件中恢复这些对象。
     */

    /*
      1. NSKeyedArchiver
     使用NSKeyedArchiver配套使用的还有一个NSKeyedUnarchiver类,其中,NSKeyedArchiver负责将对象归档到指定的文件中,而NSKeyedUnarchiver则负责从文件中恢复这些对象。
     NSKeyedArchiver会创建一种所谓的带键(keyed)的归档,在这种归档格式中,无论归档哪个对象,程序都需要为该对象分配一个key(即所谓的键),当程序希望从文件中恢复这些对象时,也需要根据key进行检索。
     */

    NSDictionary *dict = @{@"Objective-C": @89, @"Rudy": @69, @"Python": @75, @"Perl": @109};

    // 创建文件目录
    [[NSFileManager defaultManager] createDirectoryAtPath:[self myPath:nil] withIntermediateDirectories:YES attributes:nil error:nil];

    //使用NSKeyedArchiver的类方法将该对象归档成myDict.archive(这个文件名可以任意指定)。
    [NSKeyedArchiver archiveRootObject:dict toFile:[self myPath:@"myDict.rachive"]];

    //恢复指定的文件名对象
    NSDictionary *myDict = [NSKeyedUnarchiver unarchiveObjectWithFile:[self myPath:@"myDict.rachive"]];
    NSLog(@"myDict = %@", myDict);


    /*
     实现NSCoding协议
     使用NSKeyedArchiver和NSKeyedUnarchiver进行归档和恢复非常简单,如果尝试使用NSKeyedArchiver将一个自定义的对象归档到指定文件中,运行程序将会提示错误。
     实际上,如果程序需要归档、恢复任何自定义类的实例,那么该类应该实现NSCoding协议:
     initWithCoder 该方法负责恢复对象。
     encodeWithCoder该方法负责归档对象。
     当程序归档某个对象时,总会调用encodeWithCoder方法;当程序恢复某个对象时,总会调用initWithCoder方法。
     一般来说,如果对象的成员变量是Objective-C类型,并且实现了NSCoding协议,则可以直接调用encodingObject:forKey:方法来归档该成员变量,是用decodeObjectForKey:方法来恢复该成员变量;如果对象的成员变量是Objective-C类型,但没有实现NSCoding协议,那么归档该类的实例就比较困难。
     */

    KFApple *apple = [[KFApple alloc] initWithColor:@"红色" weight:3.4 size:20];
    [NSKeyedArchiver archiveRootObject:apple toFile:[self myPath:@"myApple.archive"]];

    KFApple *myApple = [NSKeyedUnarchiver unarchiveObjectWithFile:[self myPath:@"myApple.archive"]];
    NSLog(@"myAppleInfo = %@", [myApple description]);

    /*
     2. 是用NSData完成自定义归档
     前面已经提到,使用NSKeyedArchiver或NSKeyedUnarchiver的类方法来归档或恢复对象,这种方式虽然简单、易用,但每次总是将单个对象作为root进行归档或恢复。如果程序需要归档、恢复更多的对象,那么可以借助NSMutableData来创建NSKeyedArchiver或NSKeyedUnarchiver对象。
     */

    NSSet *set = [NSSet setWithObjects:@"疯狂iOS讲义", @"Android讲义", @"ajax讲义", nil];

    //创建一个NSMutableData对象,用于保存归档数据
    NSMutableData *mData = [NSMutableData data];

    //以NSMutableData对象作为参数,创建NSKeyedArchiver
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:mData];

    //重复调用encodeObject:forKey方法归档所有需要归档对象.
    [archiver encodeObject:dict forKey:@"myDict"];
    [archiver encodeObject:apple forKey:@"myApple"];
    [archiver encodeObject:set forKey:@"mySet"];
    [archiver finishEncoding];  //结束归档

    //将NSData缓存区保存的数据写入文件
    if (![mData writeToFile:[self myPath:@"myData.archive"] atomically:YES]) {
        NSLog(@"归档失败");
    }


    //以NSData作为参数,创建NSKeyedUnarchiver对象
    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:[NSData dataWithContentsOfFile:[self myPath:@"myData.archive"]]];

    //重复调用decodeObjectForKey:方法恢复所有需要恢复的对象
    NSDictionary *myDict2 = [unarchiver decodeObjectForKey:@"myDict"];
    KFApple *myApple2 = [unarchiver decodeObjectForKey:@"myApple"];
    NSSet *set2 = [unarchiver decodeObjectForKey:@"mySet"];
    [unarchiver finishDecoding];    //结束恢复

    NSLog(@"myDict2 = %@", myDict2);
    NSLog(@"myApple2 = %@", myApple2);
    NSLog(@"set2 = %@", set2);


    /*
     使用归档实现深复制
     归档会将整个对象转换为字节数据——包括该对象的所有成员变量,如果该成员变量指向另一个Objective-C对象,归档时也会归档该成员变量所指向的Objective-C对象。这表明:当程序归档一个对象时,系统会把该对象关联的所有数据都转换为字节数据;如果程序从这些字节数据中恢复这些对象,那么恢复出来的对象与原来对象将完全相同,但没有任何共用的部分,这就实现了深复制。
     */

    NSDictionary *dict2 = @{@"one": [[KFApple alloc] initWithColor:@"橙色" weight:5.4 size:80], @"two": [[KFApple alloc] initWithColor:@"白色" weight:4.4 size:23]};
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:dict2];  //将对象写入NSData中归档

    NSDictionary *dictCopy = [NSKeyedUnarchiver unarchiveObjectWithData:data];

    KFApple *app = dictCopy[@"one"];
    app.color = @"黄色";

    KFApple *app1 = dict2[@"one"];
    NSLog(@"app1.color = %@", app1.color);  //橙色

}

- (NSString *)myPath:(NSString *)childPath {
    NSString *myPath = [[NSHomeDirectory() stringByAppendingPathComponent:@"myArchive"] stringByAppendingPathComponent:childPath];
    return myPath;
}
@end


//—————KFApple.h—————
#import <Foundation/Foundation.h>
@interface KFApple : NSObject<NSCoding> // 遵循NSCoding协议,可以让KFApple实现协议中定义的initWithCoder: 和encodeWithCoder: 两个方法。

@property (nonatomic, copy) NSString *color;
@property (nonatomic, assign) float weight;
@property (nonatomic, assign) int size;

- (instancetype)initWithColor:(NSString *)color weight:(float)weight size:(int)size;
@end


//—————KFApple.m—————
#import "KFApple.h"

@implementation KFApple

- (instancetype)initWithColor:(NSString *)color weight:(float)weight size:(int)size {
    if ([super init]) {

        self.color = color;
        self.weight = weight;
        self.size = size;
    }
    return self;
}

/*
如果输出一个数组@[@"color", @"weight", @"size"],打印出来的信息应该是:
 (
 color,
 weight,
 size
 )
 而如果是自定义的类,则默认会输出<KFApple: 0x7fe292f37ff0>类似这样的信息,这种内容不太有用,这时如果想要看到该类的成员属性则可以覆写父类的此方法。
 */
- (NSString *)description {
    return [NSString stringWithFormat:@"<KFApple [_color=%@, _weight=%f, _size=%d]>", self.color, self.weight, self.size];  // 返回一个字符串
}

// 该方法负责归档对象。
- (void)encodeWithCoder:(NSCoder *)aCoder {
    //调用NSCoder的方法归档该对象的每个成员变量
    [aCoder encodeObject:_color forKey:@"color"];
    [aCoder encodeFloat:_weight forKey:@"weight"];
    [aCoder encodeInt:_size forKey:@"size"];
}

// 该方法负责恢复对象。
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    //使用NSCoder依次恢复color/weight/size这三个key所对应的value,并将恢复的value赋给当前对象的3歌成员变量。
    _color = [aDecoder decodeObjectForKey:@"color"];
    _weight = [aDecoder decodeFloatForKey:@"weight"];
    _size = [aDecoder decodeIntForKey:@"size"];
    return self;
}
@end

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值