一、简述
OC是运行时语言,只有在程序运行时,才会去确定对象的类型,并调用类与对象相应的方法。利用runtime机制让我们可以在程序运行时动态修改类、对象中的所有属性、方法,另外ios的方法调用机制并非是指针的寻址调用,而是发消息,发送消息是通过objc_msgSend(id, SEL, ...)来实现的,它首先会在对象的类对象的cache,methodlist以及父类对象的cache,methodlist中依次查找SEL对应 的IMP。
二、对象和方法结构
OC中一切都被设计成了对象,但是本质上还是C类型设计的结构体,在runtime中可以看到具体的结构。
foundation中NSObject的结构定义
@interface NSObject <NSObject> {
Class isa OBJC_ISA_AVAILABILITY;
}
我们可以在<objc.h>文件里看到Class的定义
typedef struct objc_class *Class;
typedef struct objc_object {
Class isa;
} *id;
Class 是一个 objc_class 结构类型的指针, id是一个 objc_object 结构类型的指针.
run time 中的object结构
//类在runtime中的表示
struct objc_class {
Class isa;//指针,顾名思义,表示是一个什么,
//实例的isa指向类对象,类对象的isa指向元类
#if!__OBJC2__Class super_class;//指向父类
const char*name;//类名
long version; //类的版本信息,默认为0
long info;//供运行期使用的一些位标识。
long instance_size;//该类的实例变量大小
struct objc_ivar_list *ivars;//成员变量列表
struct objc_method_list **methodLists;//方法列表
struct objc_cache *cache;//缓存//一种优化,调用过的方法存入缓存列表,下次调用先找缓存
struct objc_protocol_list *protocols;//协议列表
#endif
} OBJC2_UNAVAILABLE;
/* Use `Class` instead of `struct objc_class *` */
成员变量列表
struct objc_ivar_list {
int ivar_count OBJC2_UNAVAILABLE;
#ifdef __LP64__
int space OBJC2_UNAVAILABLE;
#endif
/* variable length structure */
struct objc_ivar ivar_list[1] OBJC2_UNAVAILABLE;
} OBJC2_UNAVAILABLE; OBJC2_UNAVAILABLE;
方法列表
struct objc_method_list {
struct objc_method_list *obsolete OBJC2_UNAVAILABLE;
int method_count OBJC2_UNAVAILABLE;
#ifdef __LP64__
int space OBJC2_UNAVAILABLE;
#endif
/* variable length structure */
struct objc_method method_list[1] OBJC2_UNAVAILABLE;
} OBJC2_UNAVAILABLE; OBJC2_UNAVAILABLE;
缓存列表
struct objc_cache {
unsigned int mask /* total = mask + 1 */ OBJC2_UNAVAILABLE;
unsigned int occupied OBJC2_UNAVAILABLE;
Method buckets[1] OBJC2_UNAVAILABLE;
};
协议列表
struct objc_protocol_list {
struct objc_protocol_list *next;
long count;
__unsafe_unretained Protocol *list[1];
};
三、方法列举展示
获取属性列表
OBJC_EXPORT objc_property_t *class_copyPropertyList(Class cls, unsigned int *outCount)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0);
for example:
unsigned int count;
//获取属性列表
objc_property_t *propertyList = class_copyPropertyList([self class], &count);
for (unsigned int i=0; i<count; i++) {
const char *propertyName = property_getName(propertyList[i]);
NSLog(@"property---->%@", [NSString stringWithUTF8String:propertyName]);
}
获取方法列表
OBJC_EXPORT Method *class_copyMethodList(Class cls, unsigned int *outCount)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0);
for example:
unsigned int count;
//获取方法列表
Method *methodList = class_copyMethodList([self class], &count);
for (unsigned int i; i<count; i++) {
Method method = methodList[i];
NSLog(@"method---->%@", NSStringFromSelector(method_getName(method)));
}
获取成员变量列表
OBJC_EXPORT Ivar *class_copyIvarList(Class cls, unsigned int *outCount)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0);
for example:
unsigned int count;
//获取成员变量列表
Ivar *ivarList = class_copyIvarList([self class], &count);
for (unsigned int i; i<count; i++) {
Ivar myIvar = ivarList[i];
const char *ivarName = ivar_getName(myIvar);
NSLog(@"Ivar---->%@", [NSString stringWithUTF8String:ivarName]);
}
获取协议列表
OBJC_EXPORT Protocol * __unsafe_unretained *class_copyProtocolList(Class cls, unsigned int *outCount)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0);
for example:
unsigned int count;
//获取协议列表
__unsafe_unretained Protocol **protocolList = class_copyProtocolList([self class], &count);
for (unsigned int i; i<count; i++) {
Protocol *myProtocal = protocolList[i];
const char *protocolName = protocol_getName(myProtocal);
NSLog(@"protocol---->%@", [NSString stringWithUTF8String:protocolName]);
}