iOS 序列化与反序列化

研究了一下 NSKeyedArchiver 和 NSKeyedUnarchiver ,其中遇到了一个麻烦的问题,研究许久才找到问题,在此留念吧!

概述:

  1. 序列化是iOS数据持久化中的一种方式,其他的方式包括plist 文件, 数据库, NSUserDefaults 等,而序列化相对于其他几种方式的的优点是它可以持久化对象,或者说类。

   2. 如果对象是NSString, NSDictionary , NSArray , NSData, NSNumber 等类型,可以直接使用NSKeyedArchiver 进行归档和NSKeyedUnarchiver 进行恢复;

3. 不是所有的对象都可以使用这种方法,只有遵守了NSCoding 协议的对象才可以,NScoding 的协议有两个,分别是:

encodeWithCoder: 每次归档对象时,都会调相应的这个方法,在这个方法里指定如果归档对象中的每个实力变量,可以使用encodeObjec:forKey: 方法归档其中的实例变量;

initWithCoder: 每次从文件中恢复对象时,都会调用这个方法,在这个方法中指定如何解码文件中的数据为对象的实例变量,可以使用decodeObject:forKey: 方法解码实例变量;


下面是具体的测试代码:

//viewController.m

#import "ViewController.h"
#import "ArchiverDataModel.h"
@interface ViewController ()<NSKeyedArchiverDelegate,NSKeyedUnarchiverDelegate>{
    NSMutableArray *_array;
}

@property (retain, nonatomic) ArchiverDataModel *dataModel;


@end

@implementation ViewController
@synthesize dataModel;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)addButtonFrame:(CGRect)frame title:(NSString *)title selecter:(SEL)selecter{
    UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    button.frame = frame;
    [button setTitle:title forState:UIControlStateNormal];
    [button addTarget:self action:selecter forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];
}

- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view.
    self.view.backgroundColor = [UIColor grayColor];
    
    [self addButtonFrame:CGRectMake(100, 100, 120, 40) title:@"归档" selecter:@selector(archiver:)];
    [self addButtonFrame:CGRectMake(100, 200, 120, 40) title:@"解档" selecter:@selector(unArchiver:)];
    
    self.dataModel.name = @"123";
    self.dataModel.age = 123;
    
    _array = [[NSMutableArray alloc]initWithArray:@[@"1",@"2",@"3"]];
    
    
    
}

- (void)archiver:(UIButton *)button{
    
    /*
     普通变量的序列化
     
    NSString *filePath = @"/Users/tongkun/Desktop/archiver.archiv";
    NSMutableData *data = [[NSMutableData alloc]init];
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]initForWritingWithMutableData:data];
    [archiver encodeObject:self.dataModel forKey:@"dataModel"];
    [archiver encodeObject:_array forKey:@"array"];
    [archiver encodeInt:10 forKey:@"int"];
    [archiver finishEncoding];
    BOOL ret = [data writeToFile:filePath atomically:YES];
    NSLog(@"ret: %d",ret);
     */
    
    NSString *filePath = @"/Users/tongkun/Desktop/archiver.archiv"; //扩展名可以随便取
    NSMutableData *data = [[NSMutableData alloc]init];
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]initForWritingWithMutableData:data];
    archiver.delegate = self;
    ArchiverDataModel *model = [[ArchiverDataModel alloc]init];
    model.name = @"name";
    model.age = 1;
    [archiver encodeObject:model forKey:@"dataModel"];
    /* 
     此处我尝试用ArchiverDataModel 作为self的属性进行归档,归档也能成功,但是并不调用对象类中的encodeWithCoder:方法,
但是文件恢复(解码)不出来,也并没有调用对象类中的initWithCoder: 方法,暂时没找到解决办法,所以只能创建一个独立的ArchiverDataModel变量进行测试了
     */
    [archiver finishEncoding];
    BOOL ret = [data writeToFile:filePath atomically:YES];
    NSLog(@"ret: %d",ret);
    
}


- (void)unArchiver:(UIButton *)button{
    /*
     普通的归档的恢复
     
    NSString *filePath = @"Users/tongkun/Desktop/archiver.archiv";
    NSData *data = [NSData dataWithContentsOfFile:filePath];
    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc]initForReadingWithData:data];
    NSArray *array = [unarchiver decodeObjectForKey:@"array"];
    int i = (int)[unarchiver decodeObjectForKey:@"int"];
    NSLog(@"array: %@, i: %d",array, i);
     */
    
    NSString *filePath = @"/Users/tongkun/Desktop/archiver.archiv";
    NSData *data = [NSData dataWithContentsOfFile:filePath];
    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc]initForReadingWithData:data];
    unarchiver.delegate = self;
    ArchiverDataModel *model = [unarchiver decodeObjectForKey:@"dataModel"];
    [unarchiver finishDecoding];
    NSLog(@"model.name : %@, model.age : %ld",model.name, model.age);
    
}
#pragma -mark 
#pragma -mark NSKeyedArchiver / NSKeyedUnarchiver Delegate
- (void)archiverDidFinish:(NSKeyedArchiver *)archiver{
    NSLog(@"archiverDidFinish");
}

- (void)unarchiverDidFinish:(NSKeyedUnarchiver *)unarchiver{
    NSLog(@"unarchiverDidFinish");
}




- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

//对象中的NSCoding 协议的实现

// ArchiverDataModel.h

#import "ArchiverDataModel.h"

@implementation ArchiverDataModel

@synthesize name;
@synthesize age;


- (void)encodeWithCoder:(NSCoder *)aCoder{
    [super encodeWithCoder:aCoder]; //如果父类也实现NSCoding 协议则应该写这句
    [aCoder encodeObject:name forKey:@"name"];
    [aCoder encodeInteger:age forKey:@"age"];
}


//对属性解码,解归档调用
- (id)initWithCoder:(NSCoder *)aDecoder{
    self = [super init];
    if (self) {
        self.name = [aDecoder decodeObjectForKey:@"name"];
        self.age = [aDecoder decodeIntegerForKey:@"age"];
    }
    return self;
}



@end


暂时就先测试这么多,以后用到得时候在继续完善!!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值