runtime 自动归档

提到归档这块,首先得看了一下,常规的归档方法(又名序列化),把对象转为字节码,以文件的形式存储到磁盘上;程序运行过程中或者当再次重写打开程序的时候,可以通过解归档(反序列化)还原这些对象。

注意NSCoding协议中有两个方法:

  • encodeWithCoder方法对对象属性进行编码,在对象归档时调用
  • initWithCoder方法解码归档数据来初始化对象,在对象解归档时调用
#import 

@interface UserModel : NSObject

@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSInteger age;

@end


#import "UserModel.h"

NSString *const kNameKey = @"name";
NSString *const kAgeKey = @"age";

@implementation UserModel

- (void)encodeWithCoder:(NSCoder *)aCoder {
    
    [aCoder encodeObject:self.name forKey:kNameKey];
    [aCoder encodeInteger:self.age forKey:kAgeKey];
}

- (id)initWithCoder:(NSCoder *)aDecoder {
    if (self == [super init]) {
        self.name = [aDecoder decodeObjectForKey:kNameKey];
        self.age = [aDecoder decodeIntegerForKey:kAgeKey];
    }
    return self;
}

@end

//归档(序列化)

// Content
UserModel *model = [[UserModel alloc] init];
model.name = @"Yang";
model.age = 22;

// save
NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingString:kYangPath];

NSMutableData *archiverData = [NSMutableData data];
NSKeyedArchiver * archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:archiverData];
[archiver encodeObject:model forKey:kYangKey];
[archiver finishEncoding];


if ([archiverData writeToFile:filePath atomically:YES]) {
    NSLog(@"archiver success");
}

//解归档(反序列化)

//get
NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingString:kYangPath];
NSData *unarchiverData = [NSData dataWithContentsOfFile:filePath];
NSKeyedUnarchiver *unachiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:unarchiverData];
UserModel *model = [unachiver decodeObjectForKey:kYangKey];
NSLog(@"test name === %@,age === %lu",model.name,model.age);
// output: test name === Yang,age === 22
  • 归档和解归档可以用于少量数据的持久化存储和读取
  • 属性列表只能存储Foundation框架中的对象,归档除了可以归档Foundation框架中的对象以外,还可以归档实现了NSCoding协议的自定义对象
  • 通过归档创建的文件是加密的
然而我们为什么要使用runtime 进行归档呢?

在上面model中,我们的类只有2个属性:name和age,于是我们在存档和解档的时候分别对这两个属性进行了处理,万一这个类的属性很多呢?!一个一个属性写的话,肯定是超级浪费时间的,所以此时runtime 就派上用场啦

此时我们需要用到runtime 的一个优势,获取类中的所有成员属性,此处有两个方法。

OBJC_EXPORT objc_property_t *class_copyPropertyList(Class cls, unsigned int *outCount)
OBJC_EXPORT Ivar *class_copyIvarList(Class cls, unsigned int *outCount)

// 第一个参数:表示获取哪个类中的成员属性
// 第二个参数:表示这个类有多少成员属性,传入一个Int变量地址,会自动给这个变量赋值


注意class_copyPropertyList返回的仅仅是对象类的属性(@property申明的属性),而class_copyIvarList返回类的所有属性和变量(包括在@interface大括号中声明的变量),此处我们用第一种。(第二种方法也可以尝试)

详细实现

#import "BaseModel.h"
#import 

@implementation BaseModel

// 归档
- (void)encodeWithCoder:(NSCoder *)enCoder{
    //归档存储自定义对象
    unsigned int count = 0;
    //获得指向该类所有属性的指针
    objc_property_t *properties = class_copyPropertyList([self class], &count);
    for (int i =0; i < count; i ++) {
        //获得
        objc_property_t property = properties[i];
        //根据objc_property_t获得其属性的名称--->C语言的字符串
        const char *name = property_getName(property);
        NSString *key = [NSString stringWithUTF8String:name];
        // 编码每个属性,利用kVC取出每个属性对应的数值
        [enCoder encodeObject:[self valueForKeyPath:key] forKey:key];
    }
    free(properties);
}


// 解档
- (id)initWithCoder:(NSCoder *)aDecoder{
    //归档存储自定义对象
    unsigned int count = 0;
    //获得指向该类所有属性的指针
    objc_property_t *properties = class_copyPropertyList([self class], &count);
    for (int i =0; i < count; i ++) {
        objc_property_t property = properties[i];
        //根据objc_property_t获得其属性的名称--->C语言的字符串
        const char *name = property_getName(property);
        NSString *key = [NSString stringWithUTF8String:name];
        //解码每个属性,利用kVC取出每个属性对应的数值
        [self setValue:[aDecoder decodeObjectForKey:key] forKeyPath:key];
    }
    free(properties);
    return self;
}

@end
然后其他类使用,只要继承它就好了
#import "BaseModel.h"

@interface PeopleModel : BaseModel

@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSInteger age;

@end

然后.m 中基本不需要做什么,然后就可以正常使用归档或解档啦
提到一点此处用看VC,石油定缺点的,就是效率比正常代码要低一点,但是我也认为这应该是可以接受的。

备注参考

http://www.jianshu.com/p/51d33d8f63e9

你可能感兴趣的:(runtime 自动归档)