第六十三篇、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
时间: 2024-10-12 16:57:05

第六十三篇、runtime实现归解档的相关文章

Vue 2.0 深入源码分析(六) 基础篇 computed 属性详解

用法 模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的.在模板中放入太多的逻辑会让模板过重且难以维护,比如: <div id="example">{{ message.split('').reverse().join('') }}</div> <script> var app = new Vue({ el:'#example', data:{message:'hello world'} }) </script> 这样模板不再是简

“全栈2019”Java第六十三章:接口与抽象方法详解

难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第六十三章:接口与抽象方法详解 下一章 "全栈2019"Java第六十四章:接口与静态方法详解 学习小组 加入同步学习小组,共同交流与进步. 方式一:关注头条号Gorhaf,私信"Java学习小组". 方式二:关注公众号Gorhaf,回复"Java学习小组&qu

《道德经?第六十三章》体悟

释道<道德经•第六十三章> 今听碧游宫通天教主讲道:“是以圣人犹难之,故终无难矣.”深有所感,遂查其出处.原文出自<道德经>,又名<老子>. 原文 为无为,事无事,味无味.大小多少,图难于其易,为大于其细:天下难事,必作于易,天下大事,必作于细.是以圣人终不为大,故能成其大.夫轻诺必寡信,多易必多难.是以圣人犹难之,故终无难矣. 译文 以无为的态度去有所作为,以不滋事的方法去处理事物,以恬淡无味当作有味.大生于小,多起于少.处理问题要从容易的地方入手,实现远大要从细微的

J2EE学习篇之--JDBC详解

今天我们来说一下关于JDBC的相关知识,关于JDBC我想大家都不陌生了,而且我记得早就开始使用它了,记得那是大二的时候做课程设计,但是那时候是为了完成任务,所以遇到问题就google,那时候也没有时间去整理,所以这次就来详细说一下关于JDBC的知识 摘要: JDBC(Java Data Base Connectivity,java数据库连接),由一些接口和类构成的API. J2SE的一部分,由java.sql,javax.sql包组成. 应用程序.JDBC API.数据库驱动及数据库之间的关系

【OpenCV入门指南】第十三篇 人脸检测

[OpenCV入门指南]第十三篇 人脸检测 本篇介绍图像处理与模式识别中最热门的一个领域--人脸检测(人脸识别).人脸检测可以说是学术界的宠儿,在不少EI,SCI高级别论文都能看到它的身影.甚至很多高校学生的毕业设计都会涉及到人脸检测.当然人脸检测的巨大实用价值也让很多公司纷纷关注,很多公司都拥有这方面的专利或是开发商业产品出售. 在OpenCV中,人脸检测也是其热门应用之一.在OpenCV的特征检测专题就详细介绍了人脸检测的原理--通过Haar特征来识别是否为人脸.Haar特征检测原理与Haa

Spring Cloud第十三篇 | Spring Boot Admin服务监控

本文是Spring Cloud专栏的第十三篇文章,了解前十二篇文章内容有助于更好的理解本文: Spring Cloud第一篇 | Spring Cloud前言及其常用组件介绍概览 Spring Cloud第二篇 | 使用并认识Eureka注册中心 Spring Cloud第三篇 | 搭建高可用Eureka注册中心 Spring Cloud第四篇 | 客户端负载均衡Ribbon Spring Cloud第五篇 | 服务熔断Hystrix Spring Cloud第六篇 | Hystrix仪表盘监控

QT开发(六十三)——QT事件机制分析

QT开发(六十三)--QT事件机制分析 一.事件机制 事件是由系统或者QT平台本身在不同的时刻发出的.当用户按下鼠标.敲下键盘,或者是窗口需要重新绘制的时候,都会发出一个相应的事件.一些事件在对用户操作做出响应时发出,如键盘事件等:另一些事件则是由系统自动发出,如计时器事件. 事件的出现,使得程序代码不会按照原始的线性顺序执行.线性顺序的程序设计风格不适合处理复杂的用户交互,如用户交互过程中,用户点击"打开文件"将开始执行打开文件的操作,用户点击"保存文件"将开始执

mysql基础篇 - SELECT 语句详解

基础篇 - SELECT 语句详解 SELECT语句详解 一.实验简介 SQL 中最常用的 SELECT 语句,用来在表中选取数据,本节实验中将通过一系列的动手操作详细学习 SELECT 语句的用法. 二.实验准备 在正式开始本实验内容之前,需要先下载相关数据库表,搭建好一个名为mysql_shiyan 的数据库(有三张表:department,employee,project),并向其中插入数据. 具体操作如下,首先输入命令进入 /home/shiyanlou/Desktop 目录: cd /

第十三篇 Integration Services:SSIS变量

本篇文章是Integration Services系列的第十三篇,详细内容请参考原文. 简介在前一篇我们结合了之前所学的冒泡.日志记录.父子模式创建一个自定义的SSIS包日志记录模式.在这一篇,我们将升级我们的解决方案为SQL Server 2012 Integration Services,演示SSIS变量,变量配置和表达式管理动态值.在前面的练习中我们已经使用过变量,但我们没有深入学习,这一篇,我们将关注SSIS变量.…………一旦安装好,你可以设置主题颜色,工具->选项->环境->常