归档和偏好设置

由于直接写入plist文件的局限性,不能够存储自定义对象,所以就有了归档,NSStringNSDictionaryNSArrayNSDataNSNumber等类型的对象,可以直接用NSKeyedArchiver进行归档和恢复,因为它们内部实现了NSCoding协议,比如NSString实现了NSSecureCoding,而NSSecureCoding实现了NSCoding协议,不是所有的对象都可以直接用这种方法进行归档,只有遵守了NSCoding协议的对象才可以,而归档和解档的过程很像我们在URL请求的时候进行encode和decode的过程,而在归档自定义对象的时候,如果子类对象也需要归档那么,在子类对象实现encodeWithCoder和initWithCoder方法的时候要先调用父类的encodeWithCoder和initWithCoder。

归档的特点:

–支持复杂的数据对象,包括自定义对
–对自定义对象进行归档处理,对象中的属性需要是基本数据类型,或者是实现了NSCoding协议的对象实例
–自定义对象的类也需要实现NSCoding;

归档和解档常用方法:

encodeWithCoder:
–每次归档对象时,都会调用这个方法。一般在这个方法里面指定如何归档对象中的每个实例变量,可以使用encodeObject:forKey:方法归档实例变量
initWithCoder:
–每次从文件中恢复(解码)对象时,都会调用这个方法。一般在这个方法里面指定如何解码文件中的数据为对象的实例变量,可以使用decodeObject:forKey:方法解码实例变量

归档数组:

//获取document目录
    //NSUserDomainMask从用户文件夹开始找 YES代表代表展开路径中的波浪字符“~”
    NSArray *documet=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
	
    NSString *doc=documet[0];
    //归档 如果归档为plist文件不需要用load的方式加载
    NSString *ahPath=[doc stringByAppendingString:@"array.archive"];
    
    NSArray *arr=@[@"book1",@"book2",@"book3"];
    //归档
    [NSKeyedArchiver archiveRootObject:arr toFile:ahPath];
    //解档
    NSArray *unarray= [NSKeyedUnarchiver unarchiveObjectWithFile:ahPath];
    NSLog(@"array==%@",unarray);

归档自定义对象
@implementation Person

//归档
-(void)encodeWithCoder:(NSCoder *)aCoder{
    [aCoder encodeObject:_name forKey:@"name"];
    [aCoder encodeInt:_age forKey:@"age"];
    NSData *imageData=UIImagePNGRepresentation(_image);
 
    [aCoder encodeObject:imageData forKey:@"imageData"];
}

//接档
-(id)initWithCoder:(NSCoder *)aDecoder{
    self=[super init];
    if (self) {
        [self setName:[aDecoder decodeObjectForKey:@"name"]];
        [self setAge:[aDecoder decodeIntForKey:@"age"]];
        NSData *imageData=[aDecoder decodeObjectForKey:@"imageData"];
           NSLog(@"%@",imageData);
        [self setImage:[UIImage imageWithData:imageData]];
    }
    return self;
}

+(id)initPersonWithName:(NSString *)name age:(int)age image:(UIImage *)image{
    Person *person=[[Person alloc]init];
    [person setName:name];
    [person setAge:age];
    [person setImage:image];
    return person;
}
@end

自定义对象子类对象
@implementation Student
-(id)initWithCoder:(NSCoder *)aDecoder{
    self=[super initWithCoder:aDecoder];
    if (self) {
        _no=[aDecoder decodeObjectForKey:@"no"];
    }
    return self;
}

-(void)encodeWithCoder:(NSCoder *)aCoder{
    [super encodeWithCoder:aCoder];
    [aCoder encodeObject:_no forKey:@"no"];
}

+(id)initPersonWithName:(NSString *)name age:(int)age image:(UIImage *)image no:(NSString *)no{
    Student *stu=[[Student alloc]init];
    [stu setNo:no];
    [stu setAge:age];
    [stu setImage:image];
    [stu setName:name];
    return stu;
}
@end



归档
  NSArray *arry=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *doc=arry[0];
    Person *person=[Person initPersonWithName:_nameText.text age:_ageText.text.intValue image:_iconView.image];
    NSString *path=[doc stringByAppendingString:@"person.plist"];
    [NSKeyedArchiver archiveRootObject:person toFile:path];

恢复
NSArray *arry=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *dir=arry[0];
    NSString *path=[dir stringByAppendingString:@"person.plist"];
   Person *person= [NSKeyedUnarchiver unarchiveObjectWithFile:path];
    _nameText.text=person.name;
    _ageText.text=[NSString stringWithFormat:@"%d",person.age];
    _iconView.image=person.image;
使用archiveRootObject:toFile:方法可以将一个对象直接写入到一个文件中,但有时候可能想将多个对象写入到同一个文件,那么可以使用NSData来归档对象,NSData可以为一些数据提供临时存储空间,以便随后写入文件,或者存放从磁盘读取的文件内容。可以使用[NSMutableDatadata]创建可变数据空间。

归档多个对象
NSArray *documents = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *path = [documents[0]stringByAppendingPathComponent:@"multiPersonInfo.plist"];
    
    Person *person1=[Person initPersonWithName:@"san" age:_ageText.text.intValue image:_iconView.image];
     Person *person2=[Person initPersonWithName:@"zhang" age:_ageText.text.intValue image:_iconView.image];
    Student *stu=[Student initPersonWithName:@"lisi" age:10 image:_iconView.image no:@"89757"];
    
    // 新建一块可变的数据区
    NSMutableData *data = [NSMutableData data];
    
    // 将数据区连接到一个NSKeyedArchiver对象
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]initForWritingWithMutableData:data];
    
    // 开始存档对象,存档的数据都会存储到NSMutableData中
    [archiver encodeObject:person1 forKey:@"person1"];
    [archiver encodeObject:person2 forKey:@"person2"];
    
    // 存档完毕(一定要调用这个方法!!!)
    [archiver finishEncoding];
    
    // 将存档的数据写入文件
    [data writeToFile:path atomically:YES];

恢复多个对象
  NSArray *documents = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *path = [documents[0]stringByAppendingPathComponent:@"multiPersonInfo.plist"];
    NSData *data = [NSData dataWithContentsOfFile:path];
    // 根据数据,解析成一个NSKeyedUnarchiver对象
    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc]initForReadingWithData:data];
    // 恢复对象
    Person *person1 = [unarchiver decodeObjectForKey:@"person1"];
    Person *person2 = [unarchiver decodeObjectForKey:@"person2"];
    // 恢复完毕(一定要调用这个方法)
    [unarchiver finishDecoding];

偏好设置
IOS应用都支持偏好设置,比如保存用户名、密码、字体大小等设置,iOS提供了一套标准的解决方案来为应用加入偏好设置功能,每个应用都有个NSUserDefaults实例,通过它来存取偏好设置。

存储偏好设置
NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
    [defaults setObject:@"张三" forKey:@"userName"];
    [defaults setInteger:10 forKey:@"age"];
    [[NSUserDefaults standardUserDefaults]setObject:@"mimaya" forKey:@"password"];
    //同步  如果不加会延迟
    [defaults synchronize];
读取偏好设置
NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
    NSString *name=[defaults objectForKey:@"userName"];
    NSLog(@"userName=%@",name);

注意:UserDefaults设置数据时,不是立即写入,而是根据时间戳定时地把缓存中的数据写入本地磁盘。所以调用了set方法之后数据有可能还没有写入磁盘,应用程序就终止了,出现以上问题,可以通过调用synchornize方法强制写入。





你可能感兴趣的:(ios,归档,恢复)