oc是面向对象的语言。对象可以看做我们对底层数据的抽象封装。对象有自己的成员变量,具备一些功能,有自己所属的类,甚至有父类,子类。那么oc的面相对象是怎么设计,怎么实现的?它的底层是由什么样的数据结构支持的呢?
编译
把OC编译成c/c++是我们了解OC底层实现的一种方式。
简单的clang编译
clang -rewrite-objc main.m -o main.cpp
有时候clang编译会需要一些环境,sdk支持,动态特性支持
clang -rewrite-objc -fobjc-arc -fobjc-runtime=ios-13.0.0 -isysroot /
Applications/Xcode.app/Contents/Developer/Platforms/
iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.0.sdk main.m
xcrun命令 xcode自带的命令行工具,在clang基础上进行了一些封装,编译oc代码,更简便一些
xcrun -sdk iphonesimulator clang -arch arm64 -rewrite-objc main.m -o
main-arm64.cpp (模拟器)
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main�arm64.cpp (⼿机)
gcc编译器在xcode的早期版本中使用,xcode现在的编译器是LLVM,采用三项插拔式设计。LLVM设计的最重要方面是,使用通用代码表示形式(IR),它是用来在编译器中表示代码的形式。所以LLVM可以以任何编程语言独立编写前端,并且可以为任意硬件架构独立编写后端。
clang 是LLVM一个子项目。负责编译c/c++/Objective-c。
cpp文件中的对象
LGPerson
typedef struct objc_object LGPerson;
typedef struct {} _objc_exc_LGPerson;
#endif
struct LGPerson_IMPL {
struct NSObject_IMPL NSObject_IVARS;
NSString *hobby;
};
本质是一个objc_object类型的结构体。
objc_object
struct objc_object {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
};
Class
typedef struct objc_class *Class;
objc_class
objc_class : objc_object {---}
id
typedef struct objc_object *id;
根据已有信息画个图
截屏2021-07-20 上午12.08.11.png总结下已有信息
- 对象本质是一个objc_object类型的结构体
- 对象都有一个指向objc_class结构体的指针isa
- objc_class结构体也有一个指向objc_class的指针isa
- id类型是objc_object *
难道我们isa指向会无限循环下吗,如果不会那对象objc_object 和objc_class他们之间的结构是怎么样的呢?
无论如何,我们可以看到isa指针在期中扮演这关键的角色
isa
objc源码
union isa_t {
isa_t() { }
isa_t(uintptr_t value) : bits(value) { }
uintptr_t bits;
private:
// Accessing the class requires custom ptrauth operations, so
// force clients to go through setClass/getClass by making this
// private.
Class cls;
public:
#if defined(ISA_BITFIELD)
struct {
ISA_BITFIELD; // defined in isa.h
};
bool isDeallocating() {
return extra_rc == 0 && has_sidetable_rc == 0;
}
void setDeallocating() {
extra_rc = 0;
has_sidetable_rc = 0;
}
#endif
void setClass(Class cls, objc_object *obj);
Class getClass(bool authenticated);
Class getDecodedClass(bool authenticated);
};
如果是64位系统,isa_t是联合体位域,现在iOS手机基本都是arm64架构。
ISA_BITFIELD是对位域的定义
x86_64
# elif __x86_64__
# define ISA_MASK 0x00007ffffffffff8ULL
# define ISA_MAGIC_MASK 0x001f800000000001ULL
# define ISA_MAGIC_VALUE 0x001d800000000001ULL
# define ISA_HAS_CXX_DTOR_BIT 1
# define ISA_BITFIELD \
uintptr_t nonpointer : 1; //是否是nonpointer \
uintptr_t has_assoc : 1; //是否有关联对象 \
uintptr_t has_cxx_dtor : 1; //是否有cxx析构函数 \
uintptr_t shiftcls : 44; /*MACH_VM_MAX_ADDRESS 0x7fffffe00000*/ \
uintptr_t magic : 6; //是否已完成初始化 \
uintptr_t weakly_referenced : 1; //是否被弱引用 \
uintptr_t unused : 1; //是否正在被释放 \
uintptr_t has_sidetable_rc : 1; //引用计数是否存在sideTable中 \
uintptr_t extra_rc : 8 //存储该对象的引用计数值减一后的结果, 如果够存则存在这里,不够则存在 sidetable
arm64
# if __arm64__
// ARM64 simulators have a larger address space, so use the ARM64e
// scheme even when simulators build for ARM64-not-e.
# if __has_feature(ptrauth_calls) || TARGET_OS_SIMULATOR
# define ISA_MASK 0x007ffffffffffff8ULL
# define ISA_MAGIC_MASK 0x0000000000000001ULL
# define ISA_MAGIC_VALUE 0x0000000000000001ULL
# define ISA_HAS_CXX_DTOR_BIT 0
# define ISA_BITFIELD \
uintptr_t nonpointer : 1; \
uintptr_t has_assoc : 1; \
uintptr_t weakly_referenced : 1; \
uintptr_t shiftcls_and_sig : 52; \
uintptr_t has_sidetable_rc : 1; \
uintptr_t extra_rc : 8
# define RC_ONE (1ULL<<56)
# define RC_HALF (1ULL<<7)
# else
# define ISA_MASK 0x0000000ffffffff8ULL
# define ISA_MAGIC_MASK 0x000003f000000001ULL
# define ISA_MAGIC_VALUE 0x000001a000000001ULL
# define ISA_HAS_CXX_DTOR_BIT 1
# define ISA_BITFIELD \
uintptr_t nonpointer : 1; \
uintptr_t has_assoc : 1; \
uintptr_t has_cxx_dtor : 1; \
uintptr_t shiftcls : 33; /*MACH_VM_MAX_ADDRESS 0x1000000000*/ \
uintptr_t magic : 6; // \
uintptr_t weakly_referenced : 1; \
uintptr_t unused : 1; \
uintptr_t has_sidetable_rc : 1; \
uintptr_t extra_rc : 19
# define RC_ONE (1ULL<<45)
# define RC_HALF (1ULL<<18)
位域提供了一种手段,使得可在高级语言中实现数据的压缩,节省了存储空间,同时也提高了程序的效率。
上面我们isa是一个objc_class的指针。位域是我们充分利用了指针64位的内存空间,不进存储了objc_class的指着地址,还存楚了其他对象的相关信息。
总结:
- 对象本质是一个objc_object类型的结构体
- 对象都有一个指向objc_class结构体的指针isa
- objc_class结构体也有一个指向objc_class的指针isa
- id类型是objc_object *
- isa是一个联合体位域,不仅存储了objc_class地址,还存储了对象的其他相关信息。
- 联合体位域的使用,优化了内存也提高了部分信息的查询效率。
网友评论