• 第六十三篇、runtime实现归解档


    #import <objc/runtime.h>
    #import <objc/message.h>
     
    @implementation HDFArchiveModel
     
    - (void)encodeWithCoder:(NSCoder *)aCoder {
      unsigned int outCount = 0;
      Ivar *ivars = class_copyIvarList([self class], &outCount);
      
      for (unsigned int i = 0; i < outCount; ++i) {
        Ivar ivar = ivars[i];
        
        // 获取成员变量名
        const void *name = ivar_getName(ivar);
        NSString *ivarName = [NSString stringWithUTF8String:name];
        // 去掉成员变量的下划线
        ivarName = [ivarName substringFromIndex:1];
        
        // 获取getter方法
        SEL getter = NSSelectorFromString(ivarName);
        if ([self respondsToSelector:getter]) {
          const void *typeEncoding = ivar_getTypeEncoding(ivar);
          NSString *type = [NSString stringWithUTF8String:typeEncoding];
          
          // const void *
          if ([type isEqualToString:@"r^v"]) {
            const char *value = ((const void *(*)(id, SEL))(void *)objc_msgSend)((id)self, getter);
            NSString *utf8Value = [NSString stringWithUTF8String:value];
            [aCoder encodeObject:utf8Value forKey:ivarName];
            continue;
          }
          // int
          else if ([type isEqualToString:@"i"]) {
            int value = ((int (*)(id, SEL))(void *)objc_msgSend)((id)self, getter);
            [aCoder encodeObject:@(value) forKey:ivarName];
            continue;
          }
          // float
          else if ([type isEqualToString:@"f"]) {
            float value = ((float (*)(id, SEL))(void *)objc_msgSend)((id)self, getter);
            [aCoder encodeObject:@(value) forKey:ivarName];
            continue;
          }
          
         id value = ((id (*)(id, SEL))(void *)objc_msgSend)((id)self, getter);
          if (value != nil && [value respondsToSelector:@selector(encodeWithCoder:)]) {
            [aCoder encodeObject:value forKey:ivarName];
          }
        }
      }
      
      free(ivars);
    }
     
    - (instancetype)initWithCoder:(NSCoder *)aDecoder {
      if (self = [super init]) {
        unsigned int outCount = 0;
        Ivar *ivars = class_copyIvarList([self class], &outCount);
        
        for (unsigned int i = 0; i < outCount; ++i) {
          Ivar ivar = ivars[i];
          
          // 获取成员变量名
          const void *name = ivar_getName(ivar);
          NSString *ivarName = [NSString stringWithUTF8String:name];
          // 去掉成员变量的下划线
          ivarName = [ivarName substringFromIndex:1];
          // 生成setter格式
          NSString *setterName = ivarName;
          // 那么一定是字母开头
          if (![setterName hasPrefix:@"_"]) {
            NSString *firstLetter = [NSString stringWithFormat:@"%c", [setterName characterAtIndex:0]];
            setterName = [setterName substringFromIndex:1];
            setterName = [NSString stringWithFormat:@"%@%@", firstLetter.uppercaseString, setterName];
          }
         setterName = [NSString stringWithFormat:@"set%@:", setterName];
          // 获取getter方法
          SEL setter = NSSelectorFromString(setterName);
          if ([self respondsToSelector:setter]) {
            // 获取数据的类型
            const void *typeEncoding = ivar_getTypeEncoding(ivar);
            NSString *type = [NSString stringWithUTF8String:typeEncoding];
            NSLog(@"%@", type);
            
            // const void *
            if ([type isEqualToString:@"r^v"]) {
              NSString *value = [aDecoder decodeObjectForKey:ivarName];
              if (value) {
               ((void (*)(id, SEL, const void *))objc_msgSend)(self, setter, value.UTF8String);
              }
      
              continue;
            }
            // int
            else if ([type isEqualToString:@"i"]) {
              NSNumber *value = [aDecoder decodeObjectForKey:ivarName];
              if (value != nil) {
                ((void (*)(id, SEL, int))objc_msgSend)(self, setter, [value intValue]);
              }
              continue;
            } else if ([type isEqualToString:@"f"]) {
              NSNumber *value = [aDecoder decodeObjectForKey:ivarName];
              if (value != nil) {
                ((void (*)(id, SEL, float))objc_msgSend)(self, setter, [value floatValue]);
              }
              continue;
            }
     
            // object
            id value = [aDecoder decodeObjectForKey:ivarName];
            if (value != nil) {
              ((void (*)(id, SEL, id))objc_msgSend)(self, setter, value);
            }
          }
        }
        
        free(ivars);
      }
      
      return self;
    }
     
    + (void)test {
      HDFArchiveModel *archiveModel = [[HDFArchiveModel alloc] init];
      archiveModel.archive = @"自动归档";
      archiveModel.session = "http://www.henishuo.com";
      archiveModel.totalCount = @(123);
      archiveModel.referenceCount = 10;
      archiveModel._floatValue = 10.0;
      
      NSString *path = NSHomeDirectory();
      path = [NSString stringWithFormat:@"%@/archive", path];
      [NSKeyedArchiver archiveRootObject:archiveModel
                                  toFile:path];
      
      HDFArchiveModel *unarchiveModel = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
      
    }
     
    @end
  • 相关阅读:
    我的C#入门之路_Day2
    我的C#入门之路 _ Day1
    【插件开发】VSCode插件开发全攻略(八)代码片段、设置、自定义欢迎页
    【插件开发】VSCode插件开发全攻略(六)开发调试技巧
    【插件开发】VSCode插件开发全攻略(五)跳转到定义、自动补全、悬停提示
    【插件开发】VSCode插件开发全攻略(四)命令、菜单、快捷键
    【插件开发】VSCode插件开发全攻略(三)package.json详解
    【插件开发】VSCode插件开发全攻略(二)HelloWord
    【插件开发】VSCode插件开发全攻略(七)WebView
    public/private/protected的具体区别
  • 原文地址:https://www.cnblogs.com/HJQ2016/p/5968918.html
Copyright © 2020-2023  润新知