runtime 实现 归档和解档

runtime 是一套比较底层的纯 C 语言 API, 平时写的 OC 代码都会转成 runtime 的 C 语言代码.
利用 runtime 可以动态的创建类(例如KVO的底层实现), 动态的创建修改方法和属性.
在自定义归档解档的时候 (NSCoding 技术), 当对象中的成员属性太多的时候, 需要写很多大部分重复的代码, 如果用 runtime 来动态的遍历对象的所有属性, 可以很方便的简化代码. 下面用一个 Demo 进行演示:
首先 runtime 常用的头文件有

// 遍历对象的所有属性
class_copyIvarList(<#__unsafe_unretained Class cls#>, <#unsigned int *outCount#>)

//遍历对象的所有方法
class_copyMethodList(<#__unsafe_unretained Class cls#>, <#unsigned int *outCount#>)

runtime 结合 KVC 实现归档和解档操作:

#import <objc/runtime.h>
#import <objc/message.h>

@implementation Person

// 归档
- (void)encodeWithCoder:(NSCoder *)coder{
    // 计算对象成员变量的个数
    unsigned int count = 0;   
    Ivar *ivars = class_copyIvarList([self class], &count);
    for (int i=0; i<count; ++i) {
        // 取出i位置对应的成员变量
        Ivar ivar = ivars[i];

        // 查看成员变量
        const char *ivarName = ivar_getName(ivar);

        // 生成 key
        NSString *key = [NSString stringWithFormat:@"%s", ivarName];
        // KVC 按 key 取值
        id value = [self valueForKey:key];
        //归档
        [coder encodeObject:value forKey:key];
    }
    // 释放 ivars 指针
    free(ivars);
}

// 解档
- (instancetype)initWithCoder:(NSCoder *)decoder{
    if (self = [super init]) {
        // 计算对象成员变量的个数
        unsigned int count = 0;
        Ivar *ivars = class_copyIvarList([self class], &count);
        for (int i=0; i<count; ++i) {
            // 取出i位置对应的成员变量
            Ivar ivar = ivars[i];

            // 查看成员变量
            const char *ivarName = ivar_getName(ivar);

            // 生成 key
            NSString *key = [NSString stringWithFormat:@"%s", ivarName];
            // 解档
            [self setValue:[decoder decodeObjectForKey:key] forKey:key];
        }
        // 释放 ivars 指针
        free(ivars);
    }
    return self;
}
@end

// main 函数:
Person *person = [[Person alloc] init];
person.name = @"小明";
person.age = 20;
person.height = 175.0;

//存储路径
NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
//NSLog(@"%@", documentPath);

//归档
NSString *filePath = [documentPath stringByAppendingPathComponent:@"person.dat"];
[NSKeyedArchiver archiveRootObject:person toFile:filePath];

//解档
Person *p = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
NSLog(@"%@--%d--%f", p.name, p.age, p.height);

原文地址:https://www.cnblogs.com/xiaocai-ios/p/7779758.html