OC对象的分类

2024-03-04  本文已影响0人  小冰山口

OC对象大体上分为3

  1. 实例对象 (instance object)
  2. 类对象 (class object)
  3. 元类对象(meta-class object)

上文中提到的都是实例对象(instance object)

image.png

如上图所示, 这些方法返回的NSObject类对象都指向同一片内存空间
如果要获取元类对象, 只能用object_getClass, 然后把类对象作为参数传进去, 获取到的就是元类对象.

我们来看看Class的本质是什么

image.png
typedef struct objc_class *Class;

从上面可以知道, Class的本质就是一个struct objc_class类型的结构体指针
那么, struct objc_class又是一个什么东西呢?
C++里, 结构体是可以继承的, struct objc_class 是继承自struct objc_object, 而struct objc_object就是一个只包含一个成员变量, 即isa指针的结构体, 所以这个struct objc_object本质上和NSObject没有任何区别, 因为NSObject也是

struct NSObject_IMPL {
    Class isa;
};
/// Represents an instance of a class.
struct objc_object {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;
};

那么, struct objc_class 的数据结构是这样的(截取部分):

image.png
可以看到, 成员变量就只有这4
Class isa;
Class superclass;
cache_t cache; // 方法缓存
class_data_bits_t bits; // 用于获取具体的类信息

从这里就可以看出, 类对象里面包含了

那么这个bits又包含了什么玄机呢?

image.png

bitsdata方法, 返回了一个class_rw_t的列表
具体方法实现如下:

image.png

简化下来就是这样

ptrauth_strip(bits,CLASS_DATA_BITS_RW_SIGNING_KEY) & FAST_DATA_MASK;

这就是将bits通过ptrauth_strip函数转换成另一个值, 再与上FAST_DATA_MASK, 这样就拿到了一个指针, 这个指针就指向了struct class_rw_t这样一个结构体, 那么, struct class_rw_t结构体里又有什么呢?

image.png

struct class_rw_ext_t 又是什么呢?

image.png

可以很清晰地看到, 有以下这些:

这里面还有一个struct class_ro_t结构体, 那它里面放了什么呢?

image.png

所以, 这些东西都齐了

而元类, 可以理解为特殊的类对象, 元类对象里也包含了:

让我们来看看object_getClass的内部实现

Class object_getClass(id obj)
{
    if (obj) return obj->getIsa();
    else return Nil;
}

很明显是返回的isa,
那么实例对象的isa指针指向的是类对象,
类对象的isa指针指向的是元类对象,
元类对象的isa指针指向的是基类(NSObject)的元类对象.

还有一个很容易搞混淆的方法

Class _Nullable
objc_getClass(const char * _Nonnull name)
image.png

然后沿着look_up_class一路查下去, 最后发现了这个方法:

image.png

大意是, 有一个哈希表, 存储的是类对象, 可以通过类名, 找到这个类对象, 然后返回出去. 注意, 不会返回元类对象

返回元类对象另有方法, 叫做: objc_getMetaClass

image.png

从上图就可以发现, 这两种方法得到的元类对象, 打印的地址是一样的.

上一篇 下一篇

猜你喜欢

热点阅读