有时候我们需要归档的时候,对于自定义类需要手写自动归档接档,当属性名比较多的时候一个个写容易出错,用runtime就比较通用简洁。
现在虽然手写归档和解档的时候不多了,但是自动操作还是用Runtime来实现的。
- (void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeObject:self.name forKey:@"name"];
}
- (id)initWithCoder:(NSCoder *)aDecoder{
if (self = [super init]) {
self.name = [aDecoder decodeObjectForKey:@"name"];
}
return self;
}
手动的有一个缺陷,如果属性多起来,要写好多行相似的代码,虽然功能是可以完美实现,但是看上去不是很优雅。
用runtime实现的思路就比较简单,我们循环依次找到每个成员变量的名称,然后利用KVC读取和赋值就可以完成encodeWithCoder和initWithCoder了。
#import " Student.h"
#import <objc/runtime.h>
#import <objc/message.h>
@implementation Student
- (void)encodeWithCoder:(NSCoder *)aCoder{
unsigned int outCount = 0;
Ivar *vars = class_copyIvarList([self class], &outCount);
for (int i = 0; i < outCount; i ++) {
Ivar var = vars[i];
const char *name = ivar_getName(var);
NSString *key = [NSString stringWithUTF8String:name];
id value = [self valueForKey:key];
[aCoder encodeObject:value forKey:key];
}
}
- (nullable __kindof)initWithCoder:(NSCoder *)aDecoder{
if (self = [super init]) {
unsigned int outCount = 0;
Ivar *vars = class_copyIvarList([self class], &outCount);
for (int i = 0; i < outCount; i ++) {
Ivar var = vars[i];
const char *name = ivar_getName(var);
NSString *key = [NSString stringWithUTF8String:name];
id value = [aDecoder decodeObjectForKey:key];
[self setValue:value forKey:key];
}
}
return self;
}
@end
class_copyIvarList方法用来获取当前 Model 的所有成员变量,ivar_getName方法用来获取每个成员变量的名称。
引用自:一缕殇流化隐半边冰霜
链接:https://www.jianshu.com/p/db6dc23834e3
网友评论