OC对象本质

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 指向 其父类的元类对象
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值