此篇文章涉及到Objective-C中对象相关的概念,期望可以把它们串起来,形成对它们总体的认识!
#对象
所有Objective-C对象都是C语言结构体objc_object,都包含一个isa指针:
```
/// An opaque type that represents an Objective-C class.
typedefstructobjc_class*Class;
/// Represents an instance of a class.
structobjc_object {
Class isa OBJC_ISA_AVAILABILITY;
};
```
#类
所有Objective-C类都是C语言结构体objc_class,继承自objc_object:
```
structobjc_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() {
returnbits.data();
}
...// 其他方法
}
```
class_data_bits_t的定义:
```
// data pointer
#define FAST_DATA_MASK 0x00007ffffffffff8UL
structclass_data_bits_t {
// Values are the FAST_ flags above.
uintptr_t bits;
...
public:
class_rw_t*data() {
return(class_rw_t*)(bits&FAST_DATA_MASK);
}
voidsetData(class_rw_t*newData)
{
assert(!data() || (newData->flags&(RW_REALIZING|RW_FUTURE)));
// Set during realization or construction only. No locking needed.
bits=(bits&~FAST_DATA_MASK)|(uintptr_t)newData;
}
...
}
```
#类的属性、方法、协议
##class_ro_t存储了当前类在编译期就已经确定的属性、实例变量、方法以及遵循的协议。
```
structclass_ro_t {
uint32_t flags;
uint32_t instanceStart;
uint32_t instanceSize;
#ifdef __LP64__
uint32_t reserved;
#endif
constuint8_t*ivarLayout;
constchar*name;
method_list_t*baseMethodList;
protocol_list_t*baseProtocols;
constivar_list_t*ivars;
constuint8_t*weakIvarLayout;
property_list_t*baseProperties;
method_list_t*baseMethods()const{
returnbaseMethodList;
}
};
```
baseMethodList:存储类实现的方法;
baseProtocols:存储类遵循的协议;
ivars:存储类的实例变量,关于Ivar可见:iOS Ivar;
baseProperties:存储类的属性;
编译期class_ro_t在对象中的位置:
##class_rw_t存储了当前类在运行期的属性、方法以及遵循的协议。
```
structclass_rw_t {
uint32_t flags;
uint32_t version;
constclass_ro_t*ro;
method_array_t methods;
property_array_t properties;
protocol_array_t protocols;
Class firstSubclass;
Class nextSiblingClass;
char*demangledName;
voidsetFlags(uint32_t set)
{
OSAtomicOr32Barrier(set,&flags);
}
voidclearFlags(uint32_t clear)
{
OSAtomicXor32Barrier(clear,&flags);
}
// set and clear must not overlap
voidchangeFlags(uint32_t set, uint32_t clear)
{
assert((set&clear)==0);
uint32_t oldf, newf;
do{
oldf=flags;
newf=(oldf|set)&~clear;
}while(!OSAtomicCompareAndSwap32Barrier(oldf, newf, (volatileint32_t*)&flags));
}
};
```
methods:存储类实现的方法;
properties:存储类的属性;
protocols:存储类遵循的协议;
运行期class_rw_t及class_ro_t在对象中的位置:
##class_rw_t与class_ro_t的关系
class_ro_t存放的是在编译期间就确定的;
class_rw_t是在运行期才确定,当运行runtime的realizeClass方法后,会先将class_ro_t的内容拷贝过去,然后再将当前类的分类的方法拷贝到其中。所以可以说class_rw_t是class_ro_t的超集,当然实际访问类的方法、属性等也都是访问class_rw_t中的内容。
在运行期添加方法时,会修改class_rw_t的methods列表,而不是class_ro_t中的baseMethods。
##实例变量在对象内存中的布局
例子代码:
```
// XXObject.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interfaceXXObject:NSObject
{
int_int0;
}
@property(nonatomic,assign)intint1;
@property(nonatomic,assign)intint2;
@property(nonatomic,assign)intint3;
@end
NS_ASSUME_NONNULL_END
// XXObject.m
#import "XXObject.h"
@implementationXXObject
- (instancetype)init
{
if(self=[super init]) {
_int0=3;
}
returnself;
}
@end
// main.m
intmain(intargc,constchar*argv[]) {
@autoreleasepool{
// Setup code that might create autoreleased objects goes here.
XXObject*obj=[[XXObject alloc] init];
obj.int1=4;
obj.int2=5;
obj.int3=6;
// 此处加断点
}
return0;
}
```
#方法调用
下面是Objective-C中的经典图,不但说明isa的关系,也表明了方法查找的路径。
##调用实例方法
缓存命中
查找当前类的缓存及方法
查找父类的缓存及方法
方法决议
消息转发
调用类方法的区别是在元类中查找,其他与调用实例方法是一样的。具体可参考:从源代码看 ObjC 中消息的发送 - 面向信仰编程。
#分类的方法
在运行期,dyld完成对OC镜像的符号绑定后,会把分类的实例方法、协议添加到class_rw_t的methods列表和protocols列表上,也会把分类的类方法和协议添加到类的元类上。具体可见:iOS 分类与扩展。