OC对象本质
- OC对象是基于C/C++的结构体实现的
@interface NSObject {
Class isa;
}
@end
struct NSObject_IMPL {
Class isa;
};
NSObject 对象占用多少内存
-
指针对象占用8个字节(64位)
-
NSObject
struct NSObject_IML { Class isa; }
NSObject 实际使用8个字节(Class isa;是一个指针对象)
但是编译器规定alloc的对象至少有16个字节id _class_createInstanceFromZone(Class cls, size_t extraBytes, void *zone) { void *bytes; size_t size; // Can't create something for nothing if (!cls) return nil; // Allocate and initialize size = cls->alignedInstanceSize() + extraBytes; // CF requires all objects be at least 16 bytes. if (size < 16) size = 16; if (zone) { bytes = malloc_zone_calloc((malloc_zone_t *)zone, 1, size); } else { bytes = calloc(1, size); } return objc_constructInstance(cls, bytes); }
-
CoreFoundation内部也存在内存对齐
内部alloc内存空间 位 16的倍数@Interface Student : NSObject { int _age; // 4 int _num; // 4 NSString *_name; // 8 } @end /* NSOject 本身有16个字节(isa占用8个字节) _age 占有4个字节 _num 占有4个字节 _name 占有8个字节 所以Student实例对象实际需要 24个字节 class_getInstanceSize(stu.class); //24 但是CF中alloc空间 有一个 字节组[16, 32, 48, 64....] 申请内存空间 为 16的倍数 所以Student实例对象实际申请的内存空间位 32个字节 malloc_size((__bridge const void *)stu); // 32 */ Student *stu = [[Student alloc] init]; // #import <objc/runtime.h> class_getInstanceSize(stu.class); // Student这个类初始化的实例对象占用多少内存空间 // #import <malloc/malloc.h> malloc_size((__bridge const void *)stu); // 编译器实际给stu实例对象申请的内存空间(实际的内存空间)
objc_getClass、object_getClass区别
objc_getClass
- objc-runtime.mm
- 参数为类名(字符串)
- 查找包中有没有这个名字的类 有则返回 无 则 返回nil
/***********************************************************************
* objc_getClass. Return the id of the named class. If the class does
* not exist, call _objc_classLoader and then objc_classHandler, either of
* which may create a new class.
* Warning: doesn't work if aClassName is the name of a posed-for class's isa!
**********************************************************************/
Class objc_getClass(const char *aClassName)
{
if (!aClassName) return Nil;
// NO unconnected, YES class handler
return look_up_class(aClassName, NO, YES);
}
object_getClass
- object-class.mm
- 参数为对象
- 调用对象的getIsa()方法
/***********************************************************************
* object_getClass.
* Locking: None. If you add locking, tell gdb (rdar://7516456).
**********************************************************************/
Class object_getClass(id obj)
{
if (obj) return obj->getIsa();
else return Nil;
}
- (Class)class、+ (Class)class 均返回类对象
- (Class)class {
return self -> isa;
}
+ (Class)class {
return self;
}
实例对象、类对象、元类对象 的 isa 和 superClass
- 准备数据
struct Class_IMPL {
Class isa;
Class _Nullable super_class;
};
@interface Person : NSObject
@end
@implementation Person
@end
- 实例对象的isa 指向 它的类对象
Person *p = [[Person alloc] init];
Class p_cls = objc_getClass("Person");
Class p_cls1 = [p class];
Class p_cls2 = [Person class];
/*
(lldb) p/x p->isa
(Class) $1 = 0x011d8001000080f1 Person
(lldb) p/x p_cls
(Class) $3 = 0x00000001000080f0 Person
(lldb) p/x p_cls1
(Class) $4 = 0x00000001000080f0 Person
(lldb) p/x p_cls2
(Class) $5 = 0x00000001000080f0 Person
*/
/*
# if __arm64__
# define ISA_MASK 0x007ffffffffffff8ULL
# elif __x86_64__
# define ISA_MASK 0x00007ffffffffff8ULL
# else
# endif
实例对象的isa指向 类对象 但是指针数据是经过位运算的出来的 p->isa & ISA_MASK = p_cls.
*/
- 类对象的isa 指向 它的元类对象
Class p_cls = objc_getClass("Person");
struct Class_IMPL *impl_p_cls = (__bridge struct Class_IMPL *)p_cls;
// impl_p_cls
Class p_meta_cls = object_getClass(p_cls);
/*
(lldb) p/x p_cls
(Class) $0 = 0x00000001000080f8 Person
(lldb) p/x impl_p_cls
(Class_IMPL *) $1 = 0x00000001000080f8
(lldb) p/x p_meta_cls
(Class) $2 = 0x00000001000080d0
(lldb) p/x impl_p_cls->isa
(Class) $3 = 0x00000001000080d0
*/
/*
类对象的isa 指向 其元类对象 impl_p_cls->isa = p_meta_cls
*/
- 元类对象的isa 指向 它的父类的元类对象
Class p_cls = objc_getClass("Person"); // 类对象
Class p_meta_cls = object_getClass(p_cls); // 元类对象
Class super_p_cls = objc_getClass("NSObject"); // 父类 类对象
Class super_p_meta_cls = object_getClass(super_p_cls); // 父类 元类对象
struct Class_IMPL *p_meta_cls_impl = (__bridge struct Class_IMPL *)p_meta_cls;
/*
(lldb) p/x p_meta_cls
(Class) $0 = 0x00000001000080d0
(lldb) p/x p_meta_cls_impl
(Class_IMPL *) $1 = 0x00000001000080d0
(lldb) p/x super_p_meta_cls
(Class) $2 = 0x00007fff80a16360
(lldb) p/x p_meta_cls_impl->isa
(Class) $3 = 0x00007fff80a16360
*/
/*
元类对象的isa 指向 其父类的元类对象
p_meta_cls->isa == super_p_meta_cls
*/
- 实例对象superclass和类对象superclass是同一个 指向 其父类的类对象
Person *p = [[Person alloc] init];
Class superClass = p.superclass; // 这个superclass方法imp是在 Person类对象里边
Class superClass1 = Person.superclass; // 这个superclass方法imp是在 Person元类对象里边
/*
(lldb) p/x superClass
(Class) $2 = 0x00007fff80a16388 NSObject
(lldb) p/x superClass1
(Class) $3 = 0x00007fff80a16388 NSObject
*/
// 实例对象superClass和类对象的superClass一致
/*
+ (Class)superclass {
return self->getSuperclass();
}
- (Class)superclass {
return [self class]->getSuperclass();
}
*/
Class obj_class = NSObject.class;
/*
(lldb) p/x superClass
(Class) $0 = 0x00007fff80a16388 NSObject
(lldb) p/x obj_class
(Class) $1 = 0x00007fff80a16388 NSObject
*/
/*
指向 父类 类对象
*/
- 元类对象的super_class 指向其父类的元类对象
Class sub_cls = Person.class; // 子类类对象
Class super_cls = NSObject.class; // 父类类对象
Class sub_meta_cls = object_getClass(sub_cls); // 子类元类对象
Class super_meta_cls = object_getClass(super_cls); // 父类元类对象
// 转换
struct Class_IMPL *impl_sub_meta_cls = (__bridge struct Class_IMPL *)sub_meta_cls;
/*
(lldb) p/x sub_meta_cls
(Class) $0 = 0x00000001000080e0
(lldb) p/x impl_sub_meta_cls
(Class_IMPL *) $1 = 0x00000001000080e0
*/
/*
(lldb) p/x super_meta_cls
(Class) $2 = 0x00007fff80a16360
(lldb) p/x impl_sub_meta_cls->super_class
(Class) $3 = 0x00007fff80a16360
*/
// impl_sub_meta_cls->super_class = super_meta_cls
/*
元类对象的superclass 指向 其父类的元类对象
*/