利用runtime 实现自动化归档

1.类的头文件遵守<NSCoding>

@interface StudentModel : NSObject<NSCoding>

2.通过运行时,获取类中的所有成员属性,这里用到了运行时的方法

// Ivar:成员属性的意思
// 第一个参数:表示获取哪个类中的成员属性
// 第二个参数:表示这个类有多少成员属性,传入一个Int变量地址,会自动给这个变量赋值
// 返回值Ivar *:指的是一个ivar数组,会把所有成员属性放在一个数组中,通过返回的数组就能全部获取到。
OBJC_EXPORT Ivar *class_copyIvarList(Class cls, unsigned int *outCount)

于是我们需要写一个方法,来返回一个数组类中的所有属性名称

// 返回self的所有对象名称
+ (NSArray *)propertyOfSelf{
    unsigned int count;
    
    // 1. 获得类中的所有成员变量
    Ivar *ivarList = class_copyIvarList(self, &count);
    
    NSMutableArray *properNames =[NSMutableArray array];
    for (int i = 0; i < count; i++) {
        Ivar ivar = ivarList[i];
        
        // 2.获得成员属性名
        NSString *name = [NSString stringWithUTF8String:ivar_getName(ivar)];
        
        // 3.除去下划线,从第一个角标开始截取
        NSString *key = [name substringFromIndex:1];
        
        [properNames addObject:key];
    }
    
    return [properNames copy];
}

3.在这里,我们已经获取到类中的所有属性的名称,接着我们需要在encodeWithCoder对属性名称和属性的值进行归档操作,在这里我们遇到了一个问题,如何把属性名称和属性的值对应起来呢。

在这里我们需要知道NSStringFromSelector(方法名)返回的是一个SEL变量指向方法名中的方法

我们注意到每个属性都有两个共同的方法那就是set方法和get方法,那么我们只需要通过属性名字,创建属性名指向的方法也就是get方法,就能获取到属性名对应的值。

// 归档
- (void)encodeWithCoder:(NSCoder *)enCoder{
    // 取得所有成员变量名
    NSArray *properNames = [[self class] propertyOfSelf];
    
    for (NSString *propertyName in properNames) {
        // 创建指向get方法
        SEL getSel = NSSelectorFromString(propertyName);
        // 对每一个属性实现归档
        [enCoder encodeObject:[self performSelector:getSel] forKey:propertyName];
    }
}

4.接下来,我们需要对类实现解档方法。这里我们遇到第二个问题,如何对属性名的属性进行赋值呢?这里我们需要用到属性的set方法,利用属性名,拼接出一个set方法的字符串,并创建一个指向属性set方法的SEL变量,并且利用performSelector实现赋值。

// 解档
- (id)initWithCoder:(NSCoder *)aDecoder{
    // 取得所有成员变量名
    NSArray *properNames = [[self class] propertyOfSelf];
    
    for (NSString *propertyName in properNames) {
        // 创建指向属性的set方法
        // 1.获取属性名的第一个字符,变为大写字母
        NSString *firstCharater = [propertyName substringToIndex:1].uppercaseString;
        // 2.替换掉属性名的第一个字符为大写字符,并拼接出set方法的方法名
        NSString *setPropertyName = [NSString stringWithFormat:@"set%@%@:",firstCharater,[propertyName substringFromIndex:1]];
        SEL setSel = NSSelectorFromString(setPropertyName);
        [self performSelector:setSel withObject:[aDecoder decodeObjectForKey:propertyName]];
    }
    return  self;
}

就这样,我们实现了对一个类实现自动归档的类,下次需要创建一个Model类时,只要继承自我们编写的这个类,就能实现自动归档啦。


你可能感兴趣的:(利用runtime 实现自动化归档)