iOS中对象的本质
我们都知道Object-C是在C\C++的基础上演化而来的,即Object-C底层还是C\C++,然后再经过汇编转换成机器语言,最后被计算机CPU所识别。
那么,我们平时写的类、对象会转换成C\C++什么数据结构类型呢?
首先,我们新建一个项目,并在项目中简单写上
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSObject *obj = [[NSObject alloc] init];
}
return 0;
}
通过点击NSObject可以进入其定义头文件中,可以发现NSObject的定义是:
@interface NSObject <NSObject> {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-interface-ivars"
Class isa OBJC_ISA_AVAILABILITY;
#pragma clang diagnostic pop
}
简化后,NSObject的定义可以写成如下格式
@interface NSObject {
Class isa OBJC_ISA_AVAILABILITY;
}
通过头文件观察,并不能够观察出什么,然后我们借助clang编译器指令:clang -rewrite-objc main.m -o main.cpp
该指令可以将main.m文件转换为C\C++代码main.cpp。
其中,rewrite-objc是重写objc语言;main.m是需要重写的文件;-o 是输出;main.cpp输出目标文件
更多学习关于clang常用语法介绍
以上转换方式,只是单存的转换为C\C++代码,并没有指明编译平台,对此,我们可以使用xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main.cpp
将main.m文件转换为iphoneos下的arm64平台下的.cpp文件。该指令会对原有指令进行响应优化。
其中xcrun是xcode run的意思;-sdk iphoneos是编译在iphoneos平台;在-arch arm64中arch是architectures构架的意思,arm64是苹果所用的构架中的一种其他还包括:arm7、arm7s等
更多学习关于iOS 中的 armv7,armv7s,arm64,i386,x86_64 都是什么
在转化完的main.cpp文件中,我们可以找到如下代码:
其中,IMPL为implementation;NSObject_IMPL即为NSObject的实现,isa其实是“is a”是一个的意思。Class可以通过进入,查看其的定义为
typedef struct objc_class *Class;
,可以看出其为一个指向结构体类型的指针。
因此,NSObject对象,在定义为
@interface NSObject {
Class isa OBJC_ISA_AVAILABILITY;
}
格式的情况下,通过内部一系列操作,最终转换为C\C++底层的代码为:
struct NSObject_IMPL {
Class isa;
};
通过观察可知NSObject_IMPL为一个结构体。
因此,NSObject对象底层实际上是一个内部有一个isa指针的结构体
更深的挖掘可以看出一下关系图:
OC对象的分类:
Objective-C中的对象分为三类:instance对象、class对象、meta-class对象
-
instance对象(实例对象):通过类alloc出来的对象,每次调用alloc都会产生新的instance对象;
所有的对象都是继承NSObject,通过以上分析,我们可知在instance里面有一个isa指针,和其他的成员变量。 -
class对象(类对象):class对象只有一个
class对象在内存中存储的信息主要包括:
isa指针
superclass指针
类的属性信息(@property)、类的对象方法信息(instance method)
类的协议信息(protocol)、类的成员变量信息(ivar)
通过查看源文件,我们可以看到 struct objc_class 的定义:
虽然我们拿到的定义已经OBJC2_UNAVAILABLE了,但是依然可以看出class里面的内容:
简化后分析可得:
typedef struct objc_class *Class;
struct objc_class {
Class isa ; // isa
Class super_class ; //super_class指针,指向meta-class
const char * name; //类的名字
long version;
long info;
long instance_size; //instances对象占用的内存空间
struct objc_ivar_list * ivars; //成员变量列表
struct objc_method_list * * methodLists;//方法列表
struct objc_cache * cache; //缓存
struct objc_protocol_list * protocols; //协议列表
} ;
当然,你也可以看下新的定义:
struct objc_class : objc_object {
// Class ISA;
Class superclass;
cache_t cache; // formerly cache pointer and vtable
class_data_bits_t bits; // class_rw_t * plus custom rr/alloc flags
class_rw_t *data() {
return bits.data();
}
void setData(class_rw_t *newData) {
bits.setData(newData);
}
void setInfo(uint32_t set) {
assert(isFuture() || isRealized());
data()->setFlags(set);
}
void clearInfo(uint32_t clear) {
assert(isFuture() || isRealized());
data()->clearFlags(clear);
}
// set and clear must not overlap
void changeInfo(uint32_t set, uint32_t clear) {
assert(isFuture() || isRealized());
assert((set & clear) == 0);
data()->changeFlags(set, clear);
}
bool hasCustomRR() {
return ! bits.hasDefaultRR();
}
void setHasDefaultRR() {
assert(isInitializing());
bits.setHasDefaultRR();
}
void setHasCustomRR(bool inherited = false);
void printCustomRR(bool inherited);
bool hasCustomAWZ() {
return ! bits.hasDefaultAWZ();
}
void setHasDefaultAWZ() {
assert(isInitializing());
bits.setHasDefaultAWZ();
}
void setHasCustomAWZ(bool inherited = false);
void printCustomAWZ(bool inherited);
bool instancesRequireRawIsa() {
return bits.instancesRequireRawIsa();
}
void setInstancesRequireRawIsa(bool inherited = false);
void printInstancesRequireRawIsa(bool inherited);
bool canAllocNonpointer() {
assert(!isFuture());
return !instancesRequireRawIsa();
}
bool canAllocFast() {
assert(!isFuture());
return bits.canAllocFast();
}
bool hasCxxCtor() {
// addSubclass() propagates this flag from the superclass.
assert(isRealized());
return bits.hasCxxCtor();
}
void setHasCxxCtor() {
bits.setHasCxxCtor();
}
bool hasCxxDtor() {
// addSubclass() propagates this flag from the superclass.
assert(isRealized());
return bits.hasCxxDtor();
}
void setHasCxxDtor() {
bits.setHasCxxDtor();
}
bool isSwiftStable() {
return bits.isSwiftStable();
}
bool isSwiftLegacy() {
return bits.isSwiftLegacy();
}
bool isAnySwift() {
return bits.isAnySwift();
}
// Return YES if the class's ivars are managed by ARC,
// or the class is MRC but has ARC-style weak ivars.
bool hasAutomaticIvars() {
return data()->ro->flags & (RO_IS_ARC | RO_HAS_WEAK_WITHOUT_ARC);
}
// Return YES if the class's ivars are managed by ARC.
bool isARC() {
return data()->ro->flags & RO_IS_ARC;
}
#if SUPPORT_NONPOINTER_ISA
// Tracked in non-pointer isas; not tracked otherwise
#else
bool instancesHaveAssociatedObjects() {
// this may be an unrealized future class in the CF-bridged case
assert(isFuture() || isRealized());
return data()->flags & RW_INSTANCES_HAVE_ASSOCIATED_OBJECTS;
}
void setInstancesHaveAssociatedObjects() {
// this may be an unrealized future class in the CF-bridged case
assert(isFuture() || isRealized());
setInfo(RW_INSTANCES_HAVE_ASSOCIATED_OBJECTS);
}
#endif
bool shouldGrowCache() {
return true;
}
void setShouldGrowCache(bool) {
// fixme good or bad for memory use?
}
bool isInitializing() {
return getMeta()->data()->flags & RW_INITIALIZING;
}
void setInitializing() {
assert(!isMetaClass());
ISA()->setInfo(RW_INITIALIZING);
}
bool isInitialized() {
return getMeta()->data()->flags & RW_INITIALIZED;
}
void setInitialized();
bool isLoadable() {
assert(isRealized());
return true; // any class registered for +load is definitely loadable
}
IMP getLoadMethod();
// Locking: To prevent concurrent realization, hold runtimeLock.
bool isRealized() {
return data()->flags & RW_REALIZED;
}
// Returns true if this is an unrealized future class.
// Locking: To prevent concurrent realization, hold runtimeLock.
bool isFuture() {
return data()->flags & RW_FUTURE;
}
bool isMetaClass() {
assert(this);
assert(isRealized());
return data()->ro->flags & RO_META;
}
// NOT identical to this->ISA when this is a metaclass
Class getMeta() {
if (isMetaClass()) return (Class)this;
else return this->ISA();
}
bool isRootClass() {
return superclass == nil;
}
bool isRootMetaclass() {
return ISA() == (Class)this;
}
const char *mangledName() {
// fixme can't assert locks here
assert(this);
if (isRealized() || isFuture()) {
return data()->ro->name;
} else {
return ((const class_ro_t *)data())->name;
}
}
const char *demangledName(bool realize = false);
const char *nameForLogging();
// May be unaligned depending on class's ivars.
uint32_t unalignedInstanceStart() {
assert(isRealized());
return data()->ro->instanceStart;
}
// Class's instance start rounded up to a pointer-size boundary.
// This is used for ARC layout bitmaps.
uint32_t alignedInstanceStart() {
return word_align(unalignedInstanceStart());
}
// May be unaligned depending on class's ivars.
uint32_t unalignedInstanceSize() {
assert(isRealized());
return data()->ro->instanceSize;
}
// Class's ivar size rounded up to a pointer-size boundary.
uint32_t alignedInstanceSize() {
return word_align(unalignedInstanceSize());
}
size_t instanceSize(size_t extraBytes) {
size_t size = alignedInstanceSize() + extraBytes;
// CF requires all objects be at least 16 bytes.
if (size < 16) size = 16;
return size;
}
void setInstanceSize(uint32_t newSize) {
assert(isRealized());
if (newSize != data()->ro->instanceSize) {
assert(data()->flags & RW_COPIED_RO);
*const_cast<uint32_t *>(&data()->ro->instanceSize) = newSize;
}
bits.setFastInstanceSize(newSize);
}
void chooseClassArrayIndex();
void setClassArrayIndex(unsigned Idx) {
bits.setClassArrayIndex(Idx);
}
unsigned classArrayIndex() {
return bits.classArrayIndex();
}
};
- meta-class对象(元类对象)
从class内部的super_class指针类型可知,元类的类型也是Class,即元类对象与类对象的结构是一样的。
可以看下图查看它们的关系:
注:1. 第二张关系图中,虚线上的class更改为isa可能更好理解一些 2. 第二张关系图中RootClass中没有superclass是不对的 3.第二张关系图中isa、superclass前面是不带*的,因为Class本身就是指针。第二张图中的错误真是。。。
总结:
每一个实例对象里面都有一个isa指针,指向class类对象;
每一个class类对象里面有一个isa指针,指向metaclass元类对象;
每一个class类对象里面有一个superclass指针,指向其父类的class类对象;其父类的class类对象里面也有一个superclass指针,指向根类对象;根类对象中的superclass指针为nil(而不是第二张图中的没有);
每一个metaclass元类对象里面有一个superclass指针,指向其父类的metaclass元类对象;最终指向RootMetaClass,RootMetaClass的superclass指针指向NSObject,即根类
每一个metaclass元类对象有一个isa指针,指向根元类对象;根元类对象的isa指针指向自己;
class类对象中的objc_method_list为对象方法;
metaclass元类中存放的objc_method_list是类方法;