Objective-C 对象的本质是什么
作为一个iOS开发,接触最多的可能就是Objective-C语言了,众所周知Objective-C是一种面向对象的语言,苹果用C/C++为其封装了成员变量、方法的存储和方法调用逻辑,但是具体的实现并没有暴露给我们。
分析之前,需要先新建个Command Line Tool工程,然后再main文件中写入以下代码:
@interface Ghost : NSObject
{
int age;
}
@end
@implementation Ghost
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
Ghost *ghost = [[Ghost alloc] init];
}
return 0;
}
然后需要把它转成C/C++代码,打开终端,进入main文件所在的目录,执行以下命令
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main_arm64.cpp
这个命令的意思是,把main.m文件中的代码,转换成iOS平台对应的C++代码。接下来打开main_arm64.cpp文件,搜索类名 Ghost,会找到Ghost_IMPL的结构体如下
typedef struct objc_object Ghost;
struct Ghost_IMPL {
struct NSObject_IMPL NSObject_IVARS;
int age;
};
从这里不难发现Objective-C对象的本质就是objc_object类型的结构体。结构体里面有一个NSObject_IMPL类型的结构体和一个int类型名字为age的变量,这个NSObject_IMPL又是什么呢?可以在main_arm64.cpp文件里面搜索NSObject_IMPL,会发现一个结构体如下
typedef struct objc_object NSObject;
struct NSObject_IMPL {
Class isa;
};
不难猜出,这个应该是NSobject类的底层实现,通过Xcode进入NSObject的头文件,会发现类的实现是这样的
@interface NSObject <NSObject> {
Class isa OBJC_ISA_AVAILABILITY;
}
上下对比下,可以证明猜测是正确的。并且可以看到NSObject对象里面只有一个 Class 类型的isa指针。
这个Class类型又是什么呢,可以通过Xcode进入objc.h找到如下代码
typedef struct objc_class *Class;
struct objc_object {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
};
typedef struct objc_object *id;
这里能看到Class是struct objc_class类型的指针,同时可以看到id是struct objc_object类型的指针。
那么struct objc_class内部又是什么样子的结构呢,Xcode并不能跳到定义的地方,这时候就需要查看苹果开源的代码了。
从这里下载最新源码,版本号最大的就是苹果开源的最新的代码。下载完成后解压,我下载的(objc4-818.2),用Xcode打开工程。这时候搜索struct objc_class,发现有两个文件定义了这个结构体(objc-runtime-new.h和objc-runtime-old.h),忽略old直接看new,可以找到如下定义(line 1688)
struct objc_class : objc_object {
//省略...
// Class ISA;
Class superclass;
cache_t cache; // formerly cache pointer and vtable
class_data_bits_t bits;
//省略...
}
可以看到objc_class是继承于objc_object的结构体,然后再搜索下struct objc_object,会在objc-private.h找到如下定义
struct objc_object {
private:
isa_t isa;
//省略 ...
}
发现isa指针并不是Class类型的了,那是因为苹果在64位系统,为了让指针存储更多的数据,isa指针优化成union isa_t的类型,找到isa_t的定义
union isa_t {
isa_t() { }
isa_t(uintptr_t value) : bits(value) { }
uintptr_t bits;
private:
Class cls;
void setClass(Class cls, objc_object *obj);
Class getClass(bool authenticated);
Class getDecodedClass(bool authenticated);
};
进入getClass方法里面,会发现 clsbits &= ISA_MASK,可以得知现在指向Class的指针需要再按位与ISA_MASK后才可以得到。
综上,Objective-C 中
1、实例对象是objc_object类型的结构体,里面包含isa指针和成员变量。
2、类对象是objc_class类型的结构体,因为继承于objc_object类型,所以同样包含isa指针,还有superclass指针等类的一些信息。
3、元类也是Class类型,同样也是objc_class类型的结构体。