iOS之对象归档

来源:互联网 发布:小米还原网络设置在哪 编辑:程序博客网 时间:2024/09/21 09:19
#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

0 0
原创粉丝点击