iOS-NSCoder 和 NSCoding

1、iOS提供基本的文件API、Property List序列化、SQLite、CoreData以及NSCoding,将应用数据存储到硬盘中。

对于轻量级的数据要求,NSCoding因其简单而成为一种比较合适的方式。 NSCoding是一个你需要在数据类上要实现的协议以支持数据类和数据流间的编码和解码。数据流可以持久化到硬盘。

2、是类对象本身数据的写入到本地文件。

一、NSCoder

NSCoder 是一个抽象类,抽象类不能被实例话,只能提供一些子类继承的方法。
NSKeyedUnarchiver 从二进制流读取对象。
NSKeyedArchiver 把对象写到二进制流中去。

二、NScoding

NScoding 是一个协议,主要有下面两个方法: encodeWithCoder和initWithEncoder。

// 解档方法(从coder中读取数据,保存到相应的变量中,即反序列化数据;实现NScoding协议)
- (instancetype)initWithCoder:(NSCoder *)coder;

// 归档调用方法(读取实例变量,并把这些数据写到coder中去,即序列化数据)
- (void)encodeWithCoder:(NSCoder *)coder;

encodeWithCoder就是编码,initWithCoder就是解码。 encodeWithCoder方法传入的是一个NSCoder对象,实现的时候我们就可以调用encodeObject、encodeFloat、 encodeInt等各种方法并通过指定键值进行编码。

示例代码如下:

Person.h文件

//Person.h文件
@interface Person : NSObject<NSCoding>

@property (nonatomic, assign)int ID;
@property (nonatomic, copy)NSString *card;
@property (nonatomic, assign)int age;
@property (nonatomic, copy)NSString *pName;
@property (nonatomic, strong)NSDecimalNumber *money;
@property (nonatomic, strong)NSMutableDictionary *dict;
@property (nonatomic, strong)NSMutableArray *arr;

@end

Person.m文件 

#import <objc/message.h> //包含消息机制

@implementation Person

// 设置不需要归解档的属性
- (NSArray *)ignoredNames {
    return @[@"ID",@"card"];
}

// 解档方法(从coder中读取数据,保存到相应的变量中,即反序列化数据;实现NScoding协议)
- (instancetype)initWithCoder:(NSCoder *)coder {
    if (self == [super init]) {
        // 获取所有成员变量
        unsigned int outCount = 0;
        Ivar *ivars = class_copyIvarList([self class], &outCount);
        
        for (int i = 0; i < outCount; i++) {
            Ivar ivar = ivars[i];
            // 将每个成员变量名转换为NSString对象类型
            NSString *key = [NSString stringWithUTF8String:ivar_getName(ivar)];
            
            // 忽略不需要解档的属性
            if ([[self ignoredNames] containsObject:key]) {
                continue;;
            }
            
            // 根据变量名解档取值,无论是什么类型
            id value = [coder decodeObjectForKey:key];
            // 取出的值再设置给属性
            [self setValue:value forKey:key];
            // 这两步就相当于以前的 self.age = [aDecoder decodeObjectForKey:@"_age"];
        }
        //释放内存!
        free(ivars);
    }
    return self;
}

// 归档调用方法(读取实例变量,并把这些数据写到coder中去,即序列化数据)
- (void)encodeWithCoder:(NSCoder *)coder {
    // 获取所有成员变量
    unsigned int outCount = 0;
    Ivar *ivars = class_copyIvarList([self class], &outCount);
    for (int i = 0; i < outCount; i++) {
        Ivar ivar = ivars[i];
        // 将每个成员变量名转换为NSString对象类型
        NSString *key = [NSString stringWithUTF8String:ivar_getName(ivar)];
        
        // 忽略不需要归档的属性
        if ([[self ignoredNames] containsObject:key]) {
            continue;
        }
        
        // 通过成员变量名,取出成员变量的值
        id value = [self valueForKeyPath:key];
        // 再将值归档
        [coder encodeObject:value forKey:key];
        // 这两步就相当于 [aCoder encodeObject:@(self.age) forKey:@"_age"];
    }
    //释放内存!
    free(ivars);
}

注意:

类直接继承自NSObject

1、- (instancetype)initWithCoder:(NSCoder *)coder方法中无需调用[super initWithCoder:coder],直接调用[super init]即可

2、- (void)encodeWithCoder:(NSCoder *)coder方法中不用调用super方法

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值