引入头文件#import <objc/runtime.h>
常见runtime api
-
object_getClass 获取class
- Class objClass = object_getClass([NSObject alloc]);
-
class_getName(Class _Nullable cls) 获取类名 传入class
- const char *className = class_getName(objClass);
-
objc_getMetaClass(const char * _Nonnull name) 获取元类 传入class名
- Class metaClass = objc_getMetaClass(className);
-
class_getInstanceMethod(Class _Nullable cls, SEL _Nonnull name) 获取实例方法
- Method instanceMethod = class_getInstanceMethod(objClass, @selector(xxInstanceMethod));
-
class_getClassMethod(Class _Nullable cls, SEL _Nonnull name) //获取类方法
- Method classMethod = class_getClassMethod(metaClass, @selector(xxClassMethod));
- 元类也返回类方法,和类方法地址一样
- 源码如下:
Method class_getClassMethod(Class cls, SEL sel) { if (!cls || !sel) return nil; return class_getInstanceMethod(cls->getMeta(), sel); } Class getMeta() { if (isMetaClassMaybeUnrealized()) return (Class)this;//判断是元类就返回 避免查询递归 else return this->ISA(); }
-
SEL method_getName(Method m) 从Method获取sel名
-
Method class_copyMethodList(Class cls, unsigned int outCount) //获取类cls的方法
- 示例:
//打印Class pClass的实例方法 void objc_copyMethodList(Class pClass){ unsigned int count = 0; Method *methods = class_copyMethodList(pClass, &count); NSLog(@"----------------"); NSLog(@"%s",__func__); for (unsigned int i=0; i < count; i++) { Method const method = methods[i]; //获取方法名 NSString *key = NSStringFromSelector(method_getName(method)); NSLog(@"%@实例方法: %@", pClass,key); } free(methods); }
- 示例:
-
IMP class_getMethodImplementation(Class cls, SEL sel) 获取方法实现指针
- Class pClass = object_getClass([NSObject alloc]);IMP imp = class_getMethodImplementation(pClass, @selector(xxInstanceMethod));
- 源码:
IMP class_getMethodImplementation(Class cls, SEL sel) { IMP imp; if (!cls || !sel) return nil; ... imp = lookUpImpOrNilTryCache(nil, sel, cls, LOOKUP_INITIALIZE | LOOKUP_RESOLVER); // Translate forwarding function to C-callable external version if (!imp) { //如果找不到(没有这个方法或者只声明未实现)就会找消息转发_objc_msgForward return _objc_msgForward; } return imp; }
-
const char *ivar_getName(Ivar ivar) 获取实例变量名
-
Ivar *class_copyIvarList(Class cls, unsigned int *outCount) 获取成员变量列表
-
objc_property_t *class_copyPropertyList(Class cls, unsigned int *outCount) 获取属性列表
- 示例:
//获取成员变量和属性 void objc_copyIvar_copyProperies(Class pClass){ unsigned int count = 0; Ivar *ivars = class_copyIvarList(pClass, &count); for (unsigned int i=0; i < count; i++) { Ivar const ivar = ivars[i]; //获取实例变量名 const char*cName = ivar_getName(ivar); NSString *ivarName = [NSString stringWithUTF8String:cName]; LGLog(@"class_copyIvarList:%@",ivarName); } free(ivars); unsigned int pCount = 0; objc_property_t *properties = class_copyPropertyList(pClass, &pCount); for (unsigned int i=0; i < pCount; i++) { objc_property_t const property = properties[i]; //获取属性名 NSString *propertyName = [NSString stringWithUTF8String:property_getName(property)]; //获取属性值 LGLog(@"class_copyProperiesList:%@",propertyName); } free(properties); }
- 示例:
-
const char *ivar_getTypeEncoding(Ivar ivar) 获取对应的编码。详细参见Type Encodings
-
const char *property_getName(objc_property_t prop) 获取属性名
-
const char *property_getAttributes(objc_property_t prop) 获取属性真实类型
- 举例:
打印:nickName T@"NSString",C,N,V_nickName//Person.h @property (nonatomic, copy) NSString *nickName; //使用 Class pClass = Person.class; unsigned int outCount, i; objc_property_t *properties = class_copyPropertyList(pClass, &outCount); for (i = 0; i < outCount; i++) { objc_property_t property = properties[i]; fprintf(stdout, "%s %s\n", property_getName(property), property_getAttributes(property)); }
说明:T: 在大写 T 后面是放的是该属性的数据类型 NSString;
C : copy;
N : nonatomic;
V: 在大写 V 后面放的是该属性的变量名称(因为我们知道 @property 实际上只是为我们编写好了 getter 和 setter 方法,并创建一个以下划线开头的变量_nickName);
详细参见官方文档.
- 举例:
-
SEL sel_registerName(const char * _Nonnull str) //获取sel