类体系结构
类核心数据结构
objc_class&Class
struct objc_class {
Class isa OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
Class super_class OBJC2_UNAVAILABLE;
const char *name OBJC2_UNAVAILABLE;
long version OBJC2_UNAVAILABLE;
long info OBJC2_UNAVAILABLE;
long instance_size OBJC2_UNAVAILABLE;
struct objc_ivar_list *ivars OBJC2_UNAVAILABLE;
struct objc_method_list **methodLists OBJC2_UNAVAILABLE;
struct objc_cache *cache OBJC2_UNAVAILABLE;
struct objc_protocol_list *protocols OBJC2_UNAVAILABLE;
#endif
} OBJC2_UNAVAILABLE;
/* Use `Class` instead of `struct objc_class *` */
/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;
objc_object&id
/// Represents an instance of a class.
struct objc_object {
Class isa OBJC_ISA_AVAILABILITY;
};
/// A pointer to an instance of a class.
typedef struct objc_object *id;
NSObject
@interface NSObject {
Class isa OBJC_ISA_AVAILABILITY;
}
//...
//...
@end
总结
- objc_class&Class是class object(class object&meta-class object)核心数据结构,class object&meta-class object类型相同,但内容不同
- objc_object&id是instance object核心数据结构,第1个数据成员固定为Class isa(指向class object),相对于instance object首地址offset为0
- NSObject是对objc_object的封装,第1个数据成员固定为Class isa(指向class object),相对于instance object首地址offset为0,oc类直接或间接继承自NSObject(root)
- instance object指针本质是id类型,但instance object会根据对应类定义做编译期检查,而id类型不做编译期检查,oc类所有方法都是运行期bind
- objc_object&NSObject的Class isa指向class object,class object的Class isa指向meta-class object,meta-class object的Class isa指向root meta-class object
- class object的super_class指向super class object,meta-class object的super_class指向super meta-class object,root class object的super_class指向Nil,root meta-class object的super_class指向root class object
- instance method(-)调用通过instance object的Class isa找到对应class object,在class object methodLists中search对应SEL的Method,找到就根据Method中的IMP调用对应函数,没有找到就循着super_class一直search,找到就调用,一直到super_class为Nil,search terminate,抛出异常或者crash
- class method(+)调用通过class object的Class isa找到对应meta-class object,在meta-class object methodLists中search对应SEL的Method,找到就根据Method中的IMP调用对应函数,没有找到就循着super_class一直search,找到就调用,一直到super_class为Nil,search terminate,抛出异常或者crash
应用
@interface FBAnimal : NSObject
@end
@implementation FBAnimal
@end
@interface FBDog : FBAnimal
@end
@implementation FBDog
@end
- (void)class_arch
{
NSObject *obj1 = [[NSObject alloc] init];
NSObject *obj2 = [[NSObject alloc] init];
Class obj1_isa = [obj1 class];
Class obj2_isa = [obj2 class];
Class objClsObj = [NSObject class];
NSLog(@"obj1_isa = %p, obj2_isa = %p, objClsObj = %p", obj1_isa, obj2_isa, objClsObj);
Class objMetaClsObj = object_getClass(objClsObj);
Class objMetaClsObj_isa = object_getClass(objMetaClsObj);
NSLog(@"objMetaClsObj = %p, objMetaClsObj_isa = %p", objMetaClsObj, objMetaClsObj_isa);
Class objClsObjSuper = class_getSuperclass(objClsObj);
Class objMetaClsObjSuper = class_getSuperclass(objMetaClsObj);
NSLog(@"objClsObjSuper = %p, objMetaClsObjSuper = %p", objClsObjSuper, objMetaClsObjSuper);
FBAnimal *animal1 = [[FBAnimal alloc] init];
FBAnimal *animal2 = [[FBAnimal alloc] init];
Class animal1_isa = [animal1 class];
Class animal2_isa = [animal2 class];
Class animalClsObj = [FBAnimal class];
NSLog(@"animal1_isa = %p, animal2_isa = %p, animalClsObj = %p", animal1_isa, animal2_isa, animalClsObj);
Class animalMetaClsObj = object_getClass(animalClsObj);
Class animalMetaClsObj_isa = object_getClass(animalMetaClsObj);
NSLog(@"animalMetaClsObj = %p, animalMetaClsObj_isa = %p", animalMetaClsObj, animalMetaClsObj_isa);
Class animalClsObjSuper = class_getSuperclass(animalClsObj);
Class animalMetaClsObjSuper = class_getSuperclass(animalMetaClsObj);
NSLog(@"animalClsObjSuper = %p, animalMetaClsObjSuper = %p", animalClsObjSuper, animalMetaClsObjSuper);
FBDog *dog1 = [[FBDog alloc] init];
FBDog *dog2 = [[FBDog alloc] init];
Class dog1_isa = [dog1 class];
Class dog2_isa = [dog2 class];
Class dogClsObj = [FBDog class];
NSLog(@"dog1_isa = %p, dog2_isa = %p, dogClsObj = %p", dog1_isa, dog2_isa, dogClsObj);
Class dogMetaClsObj = object_getClass(dogClsObj);
Class dogMetaClsObj_isa = object_getClass(dogMetaClsObj);
NSLog(@"dogMetaClsObj = %p, dogMetaClsObj_isa = %p", dogMetaClsObj, dogMetaClsObj_isa);
Class dogClsObjSuper = class_getSuperclass(dogClsObj);
Class dogMetaClsObjSuper = class_getSuperclass(dogMetaClsObj);
NSLog(@"dogClsObjSuper = %p, dogMetaClsObjSuper = %p", dogClsObjSuper, dogMetaClsObjSuper);
FBAnimal *unkonwn1 = [[FBDog alloc] init];
FBAnimal *unkonwn2 = [[FBDog alloc] init];
Class unkonwn1_isa = [unkonwn1 class];
Class unkonwn2_isa = [unkonwn2 class];
Class unkonwnClsObj = [FBDog class];
NSLog(@"unkonwn1_isa = %p, unkonwn2_isa = %p, unkonwnClsObj = %p", unkonwn1_isa, unkonwn2_isa, unkonwnClsObj);
}
output:
obj1_isa = 0x10ab82170, obj2_isa = 0x10ab82170, objClsObj = 0x10ab82170
objMetaClsObj = 0x10ab82198, objMetaClsObj_isa = 0x10ab82198
objClsObjSuper = 0x0, objMetaClsObjSuper = 0x10ab82170
animal1_isa = 0x10a3221a0, animal2_isa = 0x10a3221a0, animalClsObj = 0x10a3221a0
animalMetaClsObj = 0x10a322178, animalMetaClsObj_isa = 0x10ab82198
animalClsObjSuper = 0x10ab82170, animalMetaClsObjSuper = 0x10ab82198
dog1_isa = 0x10a3221f0, dog2_isa = 0x10a3221f0, dogClsObj = 0x10a3221f0
dogMetaClsObj = 0x10a3221c8, dogMetaClsObj_isa = 0x10ab82198
dogClsObjSuper = 0x10a3221a0, dogMetaClsObjSuper = 0x10a322178
unkonwn1_isa = 0x10a3221f0, unkonwn2_isa = 0x10a3221f0, unkonwnClsObj = 0x10a3221f0