iOS底层结构
一、Class
typedef struct objc_class *Class; struct objc_class { Class _Nonnull isa OBJC_ISA_AVAILABILITY; #if !__OBJC2__ Class _Nullable super_class OBJC2_UNAVAILABLE;/*父类*/ const char * _Nonnull name OBJC2_UNAVAILABLE;/*类名称*/ long version OBJC2_UNAVAILABLE;/*版本信息*/ long info OBJC2_UNAVAILABLE;/*类信息*/ long instance_size OBJC2_UNAVAILABLE;/*实例大小*/ struct objc_ivar_list * _Nullable ivars OBJC2_UNAVAILABLE;/*实例参数链表*/ struct objc_method_list * _Nullable * _Nullable methodLists OBJC2_UNAVAILABLE;/*类方法链表*/ struct objc_cache * _Nonnull cache OBJC2_UNAVAILABLE;/*类方法缓存*/ struct objc_protocol_list * _Nullable protocols OBJC2_UNAVAILABLE;/*协议链表*/ #endif } OBJC2_UNAVAILABLE;
二、Object
struct objc_object { Class _Nonnull isa OBJC_ISA_AVAILABILITY; };
三、Method
typedef struct objc_method *Method; struct objc_method { SEL method_name OBJC2_UNAVAILABLE;/*标示方法名称*/ char *method_types OBJC2_UNAVAILABLE;/*方法的参数类型*/ IMP method_imp 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; }
IMP
#if !OBJC_OLD_DISPATCH_PROTOTYPES typedef void (*IMP)(void /* id, SEL, ... */ ); #else typedef id (*IMP)(id, SEL, ...); #endif
SEL
typedef struct objc_selector *SEL;
四、Ivar
typedef struct ivar_t *Ivar; struct ivar_t { #if __x86_64__ // *offset was originally 64-bit on some x86_64 platforms. // We read and write only 32 bits of it. // Some metadata provides all 64 bits. This is harmless for unsigned // little-endian values. // Some code uses all 64 bits. class_addIvar() over-allocates the // offset for their benefit. #endif int32_t *offset; const char *name; const char *type; // alignment is sometimes -1; use alignment() instead uint32_t alignment_raw; uint32_t size; uint32_t alignment() const { if (alignment_raw == ~(uint32_t)0) return 1U << WORD_SHIFT; return 1 << alignment_raw; } };
五、objc_property_t
typedef struct property_t *objc_property_t; struct property_t { const char *name; const char *attributes; };
测试
@interface ViewController (){ int index; NSString *name; } @property (nonatomic,strong) UILabel *label; @end
获取ivarList
unsigned int count; Ivar *ivarList = class_copyIvarList([self class], &count); for (int i = 0; i < count; i++) { NSString *name = [NSString stringWithUTF8String:ivar_getName(ivarList[i])]; NSString *type = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivarList[i])]; long int offset = ivar_getOffset(ivarList[i]); NSLog(@"***IvarName:%@-----type:%@----offset:%ld", name, type, offset); } free(ivarList);
2018-10-03 15:48:27.742887+0800 TPNotification[3325:2368470] ***IvarName:index-----type:i----offset:848 2018-10-03 15:48:27.743003+0800 TPNotification[3325:2368470] ***IvarName:name-----type:@"NSString"----offset:856 2018-10-03 15:48:27.743109+0800 TPNotification[3325:2368470] ***IvarName:_label-----type:@"UILabel"----offset:864
获取propertyList
unsigned int count; objc_property_t *properties = class_copyPropertyList([self class], &count); for (int i =0; i < count; i++) { const char *name =property_getName(properties[i]); const char *attributes = property_getAttributes(properties[i]); NSLog(@"***propertyName:%@------attributes:%@", [NSString stringWithCString:name encoding:NSUTF8StringEncoding], [NSString stringWithCString:attributes encoding:NSUTF8StringEncoding]);
} free(properties);
2018-10-03 15:52:31.608676+0800 TPNotification[3420:2371592] ***propertyName:label------attributes:T@"UILabel",&,N,V_label
获取对象方法列表
unsigned int count; Method *methods = class_copyMethodList([self class], &count); for(int i =0; i < count; i++) { SEL name = method_getName(methods[i]); IMP imp = method_getImplementation(methods[i]); const char *type = method_getTypeEncoding(methods[i]); NSLog(@"***实例方法name:%@----IMP:%p------types:%@",NSStringFromSelector(name), imp, [NSString stringWithCString:type encoding:NSUTF8StringEncoding]); } free(methods);
2018-10-03 16:00:44.381683+0800 TPNotification[3640:2378121] ***实例方法name:viewDidLayoutSubviews----IMP:0x104b623c0------types:v16@0:8 2018-10-03 16:00:44.381764+0800 TPNotification[3640:2378121] ***实例方法name:viewDidLoad----IMP:0x104b61ee0------types:v16@0:8
获取类方法列表
unsigned int count; Method *methods =class_copyMethodList(object_getClass([self class]), &count); for (int i =0; i < count; i++) { SEL name = method_getName(methods[i]); IMP imp = method_getImplementation(methods[i]); const char *type = method_getTypeEncoding(methods[i]); NSLog(@"***类方法name:%@----IMP:%p------types:%@",NSStringFromSelector(name), imp, [NSString stringWithCString:type encoding:NSUTF8StringEncoding]); } free(methods);
2018-10-03 16:03:37.337046+0800 TPNotification[3715:2380344] ***类方法name:classMethod----IMP:0x108113470------types:v16@0:8
另一种获取类方法列表的方法
unsigned int count; const char * class_name = class_getName([self class]); Class metaClass = objc_getMetaClass(class_name); Method *methods =class_copyMethodList(metaClass, &count); for (int i =0; i < count; i++) { SEL name = method_getName(methods[i]); IMP imp = method_getImplementation(methods[i]); const char *type = method_getTypeEncoding(methods[i]); NSLog(@"***类方法name:%@----IMP:%p------types:%@",NSStringFromSelector(name), imp, [NSString stringWithCString:type encoding:NSUTF8StringEncoding]); } free(methods);
附上一张isa指针图(虚线isa指针,实线superclass指针)