NSCoding的自动归档和自动解档的正确姿势

2020-12-01  本文已影响0人  koreadragon

有时候我们需要归档的时候,对于自定义类需要手写自动归档接档,当属性名比较多的时候一个个写容易出错,用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

上一篇 下一篇

猜你喜欢

热点阅读