iOS归档使用

作者: QiShare | 来源:发表于2022-01-13 15:33 被阅读0次

对象的归档

在某种情况下,我们可能有这样的需求,需要将程序中用到的多个对象及其属性值,以及它们的相互对应关系保存到文件中,或者发送到另外的进程。为了实现这个功能,Foundation框架中,可以把互相关联的多个对象归档为二进制文件,并且还可以将对象的关系从二进制文件内还原出来。像这样,将对象打包成二进制文件就称为归档。

Foundation框架的归档功能

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

Foundation框架中的归档和系统架构是相互独立的。即PowerPC 和Intel都可以利用。在对象包含的实例变量值中,整数及实数这样的基本数据类型,以及指向其他对象的指针等都可以归档。普通指针虽然不能归档,但是根据指向的数据类型有时也可以归档的。

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

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

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

@protocol NSCoding

- (void)encodeWithCoder:(NSCoder *)coder;
- (nullable instancetype)initWithCoder:(NSCoder *)coder; // NS_DESIGNATED_INITIALIZER

@end

归档方法的定义

协议NSCoding 中,函数encodeWithCoder 定义了归档自身的方法。参数coder是传人的实例,NSKeyedArchiver的实例在 Foundation/NSKeyedArchiver.h 中。

- (void)encodeWithCoder:(NSCoder *)coder
{
   // coder encodeObject:对象 forKey:关键词字符串
   // coder encodeInteger:整数变量 forKey:关键词字符串
    //可选数据类型有多种
    [coder encodeObject:self.url forKey:@"url"];
}

如果超类适用于协议NSCoding,那么 super 将调用encodeWithCoder 对超类的实例变量进行归档。如果超类像NSObject 一样不适用于协议NSCoding,则不可调用。

解档方法的定义

为了从归档中还原对象,需要在各类定义初始化方法,即协议NSCoding 的方法initWithCoder。参数对象为coder,实际上是继承于NSCoderNSKeyedArchiver实例变量。这个对象被称解档器。 NSKeyedUnarchiver 的接口在Foundation/NSKeyedArchiver.h中定义。

- (instancetype)initWithCoder:(NSCoder *)coder
{
    //self=[super initWithCoder:coder]; 超类不适用于协议NSCoding,使用[super init]
    self=[super init];
    if(self){
        //变量=[coder decodeObjectForKey:键值];
        self.url=[coder decodeObjectForKey:@"url"];
    }
    return  self;
}

只需在编码和解码中指定相同的键值,解码即可按照任意顺序还原对象,即使有不能还原的变量也无妨。

编码方法

//将字符串作为键值来对参数对象编码
- (void)encodeObject:(nullable id)object forKey:(NSString *)key;
//在对象图中需要参数object时将字符串作为键值编码
- (void)encodeConditionalObject:(nullable id)object forKey:(NSString *)key;
//将字符串作为键值对整数参数归档
- (void)encodeInt:(int)value forKey:(NSString *)key;

解码方法

//使用指定键值来还原编码对象
- (nullable id)decodeObjectForKey:(NSString *)key;
//将键值为参数字符串的整数解码
- (int)decodeIntForKey:(NSString *)key;

归档和解档初始化方法

NSKeyedArchiver 的实例,即归档器。可将对象编码结果写入数据对象内。NSKeyedArchiver 的初始化方法为:

//将预先生成的NSMutableData 实例作为参数,初始化NSKeyedArchiver 实例。参数的数据对象被保存下来。最终生成归档。
- (instancetype)initForWritingWithMutableData:(NSMutableData *)data;
  

归档器生成后,就可使用上面介绍的encode...方法进行数据归档。编码根对象后,对象图全体会被递归地进行归档。
所有归档完成后,最后必须调用finishEncoding 方法进行后处理。

- (void)finishEncoding;

处理完成后,因归档器初始化传人的对象已经进行了归档。即可将其保存到文件中,或向其他进程发送消息。

解档器NSKeyedUnarchiver的初始化方法

//初始化接收器,将参数对象从归档中还原,参数data被保存在接收器内
- (nullable instancetype)initForReadingFromData:(NSData *)data error:(NSError **)error;

还原归档的对象图和还原一个对象是同样的,都使用方法decodeObjectForKey:

以上介绍了归档和解档实例生成方法,还有更简洁的方法也可将归档结果写入文件内,进行读取与还原。

//NSKeyedArchiver 类中的方法,通过指定根对象将归档结果写入指定路径的文件中。返回值为YES表示成功
+ (BOOL)archiveRootObject:(id)rootObject toFile:(NSString *)path;
//NSKeyedUnarchiver 类中方法,从指定路径中读出归档数据进行解档,返回根对象。处理失败则返回nil。
+ (nullable id)unarchiveObjectWithFile:(NSString *)path;

举例说明

@interface ProductModel : NSObject<NSCoding>
@property (nonatomic,copy)NSString *url;
@end
 
  #import "ProductModel.h"
@implementation ProductModel
- (instancetype)initWithCoder:(NSCoder *)coder
{
    //self=[super initWithCoder:coder]; 超类不适用于协议NSCoding,使用[super init]
    self=[super init];
    if(self){
        self.url=[coder decodeObjectForKey:@"url"];
    }
    return  self;
}

- (void)encodeWithCoder:(NSCoder *)coder
{
    [coder encodeObject:self.url forKey:@"url"];
}
@end
  
- (void)createProducts{
  ProductModel *product=[[ProductModel alloc]init];
    product.url=@"https://www.baidu.com/";
    NSString*cachePath =NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask,YES).firstObject;
    NSString *path=[cachePath stringByAppendingPathComponent:@"product"];
    NSLog(@"path:%@",path);
    [NSKeyedArchiver archiveRootObject:product toFile:path];
    id object=[NSKeyedUnarchiver unarchiveObjectWithFile:path];
    ProductModel *productModel=object;
    NSLog(@"productModel.url:%@",productModel.url);
}
  
  //打印日志为:
2021-12-29 16:09:28.443771+0800 OCTest3[496:38974] path:/var/mobile/Containers/Data/Application/E3E1CDF0-AF9D-4D0B-9425-806439F2AA0C/Library/Caches/product
2021-12-29 16:09:28.463214+0800 OCTest3[496:38974] productModel.url:https://www.baidu.com/
  

相关文章

  • 2021-08-20

    iOS swift NSKeyedArchiver 使用 iOS 中swift的归档与解挡 归档: 将对象按照一定...

  • iOS对象归档

    终结一下iOS的对象归档问题. 1:这个对象为什么需要归档 2:使用归档的时候需要注意什么 3:归档以后写进本地,...

  • iOS归档使用

    对象的归档 在某种情况下,我们可能有这样的需求,需要将程序中用到的多个对象及其属性值,以及它们的相互对应关系保存到...

  • iOS开发之归档

    对于iOS开发中的归档,最近刚好在项目中使用到了归档,所以查了查资料,查缺补漏,现总结如下:什么时候使用归档? 归...

  • iOS NSData归档

    *上一章iOS NSKeyedArchiver数据归档写到使用archiveRootObject:toFile:方...

  • iOS归档(转)

    按下home后使用归档保存model数据,返回应用后解档恢复 iOS archive(归档)的总结 - 苹果吧 -...

  • iOS---归档与解档

    /*iOS归档小结:1.归档实际上就是一种文件保存的形式,几乎所有的对象都能够被归档存储。它使用NSKeyedAr...

  • iOS数据本地化

    1.NSUserDefaults 2.归档 浅谈iOS本地数据保存 - 简书 使用NSKeyedArichiver...

  • iOS 归档反归档的简单使用

    需要本地存储一些数据,NSUserDefaults支持的数据类型有:NSNumber(NSInteger、floa...

  • oracle删除归档

    oracle删除归档,可以使用rman删除归档,也可以使用rm直接删除! 1.使用rm删除归档: 删除所有归档:f...

网友评论

    本文标题:iOS归档使用

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