1. BSClassInfo.h文件

//
//  ClassInfo
//  BSClassInfo
//  Created by yuYue on 2019/2/2.
//  Copyright © 2019 yuYue. All rights reserved.
//#import <Foundation/Foundation.h>
#import <objc/runtime.h>NS_ASSUME_NONNULL_BEGIN@interface BSIvarInfo : NSObject
@property (assign, nonatomic, readonly) Ivar ivar;
@property (copy, nonatomic, readonly) NSString *name;
@property (assign, nonatomic, readonly) ptrdiff_t offset;
@property (copy, nonatomic, readonly) NSString *typeEncoding;- (instancetype)initWithIvar:(Ivar)ivar;
@end@interface BSMethodInfo : NSObject
@property (assign, nonatomic, readonly) Method method;
@property (copy, nonatomic, readonly) NSString *name;
@property (assign, nonatomic, readonly) SEL sel;
@property (assign, nonatomic, readonly) IMP imp;
@property (copy, nonatomic, readonly) NSString *typeEncoding;
@property (copy, nonatomic, readonly) NSString *returnTypeEncoding;
@property (copy, nonatomic, readonly) NSArray<NSString *> *argumentTypeEncoding;- (instancetype)initWithMethod:(Method)method;
@end@interface BSPropertyInfo : NSObject
@property (assign, nonatomic, readonly) objc_property_t property;
@property (copy, nonatomic, readonly) NSString *name;
@property (copy, nonatomic, readonly) NSString *typeEncoding;
@property (copy, nonatomic, readonly) NSString *ivarName;
@property (assign, nonatomic, readonly) SEL getter;
@property (assign, nonatomic, readonly) SEL setter;
@property (nullable, assign, nonatomic, readonly) Class cls;
@property (nullable, copy, nonatomic, readonly) NSArray<NSString *> *protocols;- (instancetype)initWithProperty:(objc_property_t)property;@end@interface BSClassInfo : NSObject
@property (assign, nonatomic, readonly) Class cls;
@property (assign, nonatomic, readonly) Class supCls;
@property (assign, nonatomic, readonly) Class metaCls;
@property (assign, nonatomic, readonly) BOOL isMeta;
@property (copy, nonatomic, readonly) NSString *name;
@property (nullable, strong, nonatomic, readonly) BSClassInfo *superClassInfo;@property (nullable, strong, nonatomic, readonly) NSDictionary<NSString *, BSIvarInfo *> *ivarInfos;
@property (nullable, strong, nonatomic, readonly) NSDictionary<NSString *, BSMethodInfo *> *methodInfos;
@property (nullable, strong, nonatomic, readonly) NSDictionary<NSString *, BSPropertyInfo *> *propertyInfos;- (instancetype)initWithClass:(Class)cls;
@endNS_ASSUME_NONNULL_END复制代码
  1. BSClassInfo.m 文件
//
//  NSObject+BSClassInfo.m
//  ClassInfo
//
//  Created by yuYue on 2019/2/2.
//  Copyright © 2019 yuYue. All rights reserved.
//#import "BSClassInfo.h"@implementation BSIvarInfo- (instancetype)initWithIvar:(Ivar)ivar{if (!ivar) return nil;self = [super init];_ivar = ivar;const char * name = ivar_getName(ivar);if (name) {_name = [NSString stringWithUTF8String:name];}_offset = ivar_getOffset(ivar);const char * typeEncoding = ivar_getTypeEncoding(ivar);if (typeEncoding) {_typeEncoding = [NSString stringWithUTF8String:typeEncoding];}return self;
}
@end@implementation BSMethodInfo- (instancetype)initWithMethod:(Method)method{if(!method) return nil;self = [super init];_method = method;_sel = method_getName(method);const char *name = sel_getName(_sel);if (name) {_name = [NSString stringWithUTF8String:name];}_imp = method_getImplementation(method);const char *typeEncoding = method_getTypeEncoding(method);if (typeEncoding) {_typeEncoding = [NSString stringWithUTF8String:typeEncoding];}char *returnType = method_copyReturnType(method);if (returnType) {_returnTypeEncoding = [NSString stringWithUTF8String:returnType];free(returnType);}unsigned int argumentCount = method_getNumberOfArguments(method);if (argumentCount > 0) {NSMutableArray *arrM = [NSMutableArray array];for (int i = 0; i < argumentCount; i++) {char *argumentType = method_copyArgumentType(method, i);NSString *type = argumentType ? [NSString stringWithUTF8String:argumentType] : @"";[arrM addObject:type];free(argumentType);}_argumentTypeEncoding = arrM;}return self;
}@end@implementation BSPropertyInfo
- (instancetype)initWithProperty:(objc_property_t)property{if(!property) return nil;self = [super init];_property = property;const char *name  = property_getName(property);if (name) {_name = [NSString stringWithUTF8String:name];}if (_name) {_getter = NSSelectorFromString(_name);NSString *setter = [NSString stringWithFormat:@"set%@%@",[[_name substringToIndex:1]uppercaseString],[_name substringFromIndex:1]];_setter = NSSelectorFromString(setter);}unsigned int count;objc_property_attribute_t *attributs =  property_copyAttributeList(property, &count);for (int i = 0; i < count; i++) {switch (attributs[i].name[0]) {case 'T':{//typeEncoding_typeEncoding = [NSString stringWithUTF8String:attributs[i].value];if (*_typeEncoding.UTF8String == '@') {size_t len = strlen(_typeEncoding.UTF8String);if (len != 2) {//是对象NSScanner *scanner = [NSScanner scannerWithString:_typeEncoding];if (![scanner scanString:@"@\"" intoString:NULL]) continue;NSString *clsName = nil;if ([scanner scanUpToCharactersFromSet:[NSCharacterSet characterSetWithCharactersInString:@"\"<"] intoString:&clsName]) {_cls = NSClassFromString(clsName);}//protocolNSMutableArray *arrM = [NSMutableArray array];while ([scanner scanString:@"<" intoString:NULL]) {NSString *protocol;if ([scanner scanUpToString:@">" intoString:&protocol]) {if (protocol.length) {[arrM addObject:protocol];}}[scanner scanString:@">" intoString:NULL];}_protocols = arrM;}}}break;case 'V':{if (attributs[i].value) {_ivarName = [NSString stringWithUTF8String:attributs[i].value];}}break;default:break;}}return self;
}
@end@implementation BSClassInfo
- (instancetype)initWithClass:(Class)cls{if(!cls) return nil;self = [super init];_cls = cls;_supCls = class_getSuperclass(cls);_isMeta = class_isMetaClass(cls);if (!_isMeta) {_metaCls = objc_getMetaClass(class_getName(cls));}_name = [NSString stringWithUTF8String:class_getName(cls)];[self update];_superClassInfo = [[BSClassInfo alloc] initWithClass:_supCls];return self;
}- (void)update{_ivarInfos = nil;_methodInfos = nil;_propertyInfos = nil;//ivarClass cls = self.cls;unsigned int ivarCount = 0;NSMutableDictionary *dictMIvar = [NSMutableDictionary dictionary];Ivar *ivarList = class_copyIvarList(cls, &ivarCount);for (int i = 0; i < ivarCount; i++) {BSIvarInfo *ivarInfo = [[BSIvarInfo alloc] initWithIvar:ivarList[i]];[dictMIvar setObject:ivarInfo forKey:ivarInfo.name];}_ivarInfos = dictMIvar;free(ivarList);//methodNSMutableDictionary *dictMMethod = [NSMutableDictionary dictionary];unsigned int methodCount = 0;Method *methodList = class_copyMethodList(cls, &methodCount);for (int i = 0 ; i < methodCount; i++) {BSMethodInfo *methodInfo = [[BSMethodInfo alloc] initWithMethod:methodList[i]];[dictMMethod setObject:methodInfo forKey:methodInfo.name];}_methodInfos = dictMMethod;free(methodList);//propertyNSMutableDictionary *dictMProperty = [NSMutableDictionary dictionary];unsigned int propertyCount = 0;objc_property_t *propertyList = class_copyPropertyList(cls, &propertyCount);for (int i = 0; i < propertyCount; i++) {BSPropertyInfo *propertyInfo = [[BSPropertyInfo alloc] initWithProperty:propertyList[i]];[dictMProperty setObject:propertyInfo forKey:propertyInfo.name];}_propertyInfos = dictMProperty;free(propertyList);
}
@end
复制代码
  1. 总结
    以上代码是读完YYModel中的YYClassInfo源码学到的利用runtime获取类的信息。YYClassInfo源代码中有关于缓存的部分,而我们的目的是抽取runtime部分,所以这里没有做缓存。有兴趣的小伙伴可以和YYClassInfo源代码做下对比会发现有些部分会有些少许改动。其实就是按照自己的习惯写出来的代码会和源代码有些不同,但都达到了获取类信息的目的。该代码有助于理解YYModel源码以及可以进一步学习runtime知识,一举两得。

转载于:https://juejin.im/post/5cfdaf4ae51d45105d63a4dd

获取一个类的信息(仿YYClassInfo类)相关推荐

  1. 多类差异信息柔性融合概念与内涵

    摘 要:通过融合结构描述了差异信息产生的原因和特征表现.阐述了多类差异信息柔性融合的概念与内涵,根据通信时延和状态过程噪声等因素对融合性能的影响,提出了不同通信时延和状态过程噪声条件下融合结构的选择机 ...

  2. 类和接口的使用-类和成员可访问性最小化

    一个良好的程序设计应该是层次清晰,各模块对于外部模块来说,是否只提供了对外的API而隐藏了具体的实现细节,通常对于使用者而言,只需要知道实现功能的API 而无法操作具体实现的过程,这种设计理念被称为信 ...

  3. Android开发之获取手机SIM卡信息

    TelephonyManager是一个管理手机通话状态.电话网络信息的服务类,该类提供了大量的getXxx(),方法获取电话网络的相关信息. TelephonyManager类概述: 可用于访问有关设 ...

  4. mave工程中的一个类调用另一个聚合工程的一个类_信息系统管理工程师备考分享(材料重点精炼)——第一章信息化和信息系统(4)...

    本章分享的1.4节的重要考点内容相对来说还是比较多的,里面包括需求.设计.测试等软件工程的内容,同学们学完前几篇文章的分享会发现,第一章与计算机领域的知识的衔接程度还是非常紧密的.我经常会听到很多面授 ...

  5. (反射):获取一个类的父类和父类的泛型

    一.解决问题 获取一个类的父类和父类的泛型 二.实现 Student.java package Test3;public class Student {private String name;priv ...

  6. java反射 获取方法_java反射之获取类的信息方法(推荐)

    本文接上文"老生常谈反射之class类的使用(必看篇)",以编写一个用来获取类的信息(成员函数.成员变量.构造函数)的工具类来讲解"反射之获取类的信息" 1.获 ...

  7. 获取SIM卡信息的工具类

    本工具类可以获取手机的IMSI.本机的手机号码.SIM卡的服务商. 移动.联通可正常获取到SIM卡的手机卡号,但是电信的获取不到.... 首先,需要在AndroidManifest.xml清单配置文件 ...

  8. arcgis 圈选获取图层下点位_ARCGIS获取图层下的要素信息及要素类转换为要素

    /// /// 得到需要的字段名和字段值 /// /// private void GetField(ILayer layer) { int index = 0; int i = 0; //要素类转换 ...

  9. Java反射机制demo(四)—获取一个类的父类和实现的接口

    2019独角兽企业重金招聘Python工程师标准>>> Java反射机制demo(四)-获取一个类的父类和实现的接口 1,Java反射机制得到一个类的父类 使用Class类中的get ...

  10. 构造方法与重载:定义一个网络用户类,信息有用户 ID、用户密码、 email 地址。在建立类的实例时把以上三个信息都作为构造函数的参数输入

    构造方法与重载:定义一个网络用户类,信息有用户 ID.用户密码. email 地址.在建立类的实例时把以上三个信息都作为构造函数的参数输入, 其中用户 ID 和用户密码时必须缺省时 email地址是用 ...

最新文章

  1. 怎么接收layui上传的文件_layui 上传文件_批量导入数据UI的方法
  2. 【MATLAB】————拷贝指定文件路径下的有序文件(选择后),可处理固定规律的文件图片数据或者文件
  3. 某大厂程序员吐槽:老家亲戚狮子大开口,竟跟自己借八十万给儿子买房!
  4. Entity Framework Core 2.0的新特性
  5. Ubuntu系统版本升级(提前版)
  6. SDN和OpenFlow的区别—Vecloud微云
  7. 祝文欣讲座免费在线学习 免费下载
  8. python中DictVectorizer的使用
  9. rest api如何创建_REST:创建资源
  10. Linux启动芯片的初始代码,Linux系统初始化流程(简述)
  11. [HTTP] HTTP的缓存机制
  12. 第 16 章 垃圾回收相关概念
  13. Servlet(二)GenericServlet
  14. linux配置jupyterlab
  15. php 编译 sass,如何在Symfony 3中使用纯PHP编译SASS(scss)
  16. 每日一题/004/矩阵/矩阵问题转化为线性方程组问题
  17. 广州自由自在进口食品进入寻常百姓家
  18. Android及其他平台音频开源库介绍
  19. [2020-07]如何获取百度访客搜索关键字(竞价、推广、SEO)
  20. 解决 ClickOnce 发布出现: 清单中的引用与下载的程序集 *.exe 的标识不匹配 问题

热门文章

  1. 第一个Django模型
  2. Linux上的errno和strerror
  3. BaKoMa Tex Word 的使用
  4. JSP中使用的模式——JSP+Servlet+JavaBean
  5. C# 读写锁 ReaderWriteLock
  6. 仪式与工具--团队管理之规范创立与流程固化过程中必要因素
  7. 监控摄像头GB28181转RTMP、FLV、HLS、RTSP多种格式实现网页嵌入播放
  8. FineUI分组显示弹框最新的在最上边
  9. 英语六级翻译训练:教育专题
  10. Swift实现糗事百科Demo(实战项目)