runtime

结构体

包含多个变量或者数组的集合

1.结构体定义
struct 结构体名{
变量或数组
};
2.结构体定义,并且初始化结构体变量 struct1
struct 结构体名{
。。。
}结构体变量名struct1;

OC中的类

isa

每个实例对象有个isa的指针,指向对象的类,Class也有isa的指针,指向MeteClass(元类)可以理解为表明所属权,声明了实例与所属类的关系

运行时类的动态化处理(3步)

  1. objc_allocateClassPair() 为 class pair 分配类存
  2. class_addMethod() class_addIvar 添加方法或者成员变量
  3. objc_registerClssPair() 注册类

class(类) pair(元类)

Object-c的一个类也是一个对象,也可以发送消息给一个类

类(Class)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
typedef struct objc_class *Class;
struct objc_class {
Class isa OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
Class super_class OBJC2_UNAVAILABLE;
const char *name OBJC2_UNAVAILABLE;
long version OBJC2_UNAVAILABLE;
long info OBJC2_UNAVAILABLE;
long instance_size OBJC2_UNAVAILABLE;
struct objc_ivar_list *ivars OBJC2_UNAVAILABLE;
struct objc_method_list **methodLists OBJC2_UNAVAILABLE;
struct objc_cache *cache OBJC2_UNAVAILABLE;
struct objc_protocol_list *protocols OBJC2_UNAVAILABLE;
#endif
} OBJC2_UNAVAILABLE;

对象(id)

1
2
3
typedef struct objc_object {
Class isa;
} *id;
  • 对象是一个含有指向类结构的指针isa的结构体
    理解:id(每个对象)含有一个isa指向对应的类
  • Objective-C中对象最重要的特点是你可以发送消息给它们:
    1
    2
    [@"stringValue"
    writeToFile:@"/file.txt" atomically:YES encoding:NSUTF8StringEncoding error:NULL];

Objective-C对象(这儿是NSCFString)在发送消息时,运行时库会追寻着对象的isa指针得到了对象所属的类(这儿是NSCFString类)。这个类包含了能应用于这个类的所有实例方法和指向超类的指针以便可以找到父类的实例方法。运行时库检查这个类和其超类的方法列表,找到一个匹配这条消息的方法(在上面的代码里,是NSString类的writeToFile:atomically:encoding:error方法)。运行时库基于那个方法调用函数(IMP)

重点就是类要定义这个你发送给对象的消息。

元类pair

Objective-C的一个类也是一个对象。这意味着你可以发送消息给一个类。

总结说OC中所有的类都是一种对象。由一个类实例化来的对象叫实例对象,那么,类作为对象(称之为类对象),又是什么类的对象?就是元类(Metaclass)元类就是类对象所属的类。所以,实例对象是类的实例,类作为对象又是元类的实例。已经说了,OC中所有的类都属于一种对象,所以元类也是对象,那么元类是什么的实例呢?答曰:根元类,根元类是其自身的实例.也就是说根元类的元类就是它自己。基类的元类的isa指针指向他自己。

  • 当你给对象发送消息时,消息是在寻找这个对象的类的方法列表。
  • 当你给类发消息时,消息是在寻找这个类的元类的方法列表。

用一张图表明他们之间的关系:
img
注意:根元类的superclass不是nil而是根类。对于OC原生的类,根元类的父类就是系统的根类NSOject。但根类不一定是NSObject,因为后面介绍的objc_allocateClassPair函数也可创建出一个根类。

元类是必不可少的,因为它存储了类的类方法。每个类都必须有独一无二的元类,因为每个类都有独一无二的类方法

1
NSStringEncoding defaultStringEncoding = [NSString defaultStringEncoding];

在这个示例里,defaultStringEncoding被发送给了NSString类。

因为Objective-C中每个类本身也是一个对象。如上面所展示的,这意味着类结构必须以一个isa指针开始,从而可以和objc_object在二进制层面兼容,然后这个结构的下一字段必须是一个指向超类的指针(对于基类则为nil)。

实例对象、类对象、元类对象,有什么区别?

  • 实例对象:当我们在代码中new一个实例对象时,拷贝了实例所属的类的成员变量,但不拷贝类定义的方法。调用实例方法时,根据实例的isa指针去寻找方法对应的函数指针。

  • 类对象:是一个功能完整的对象。特殊之处在于它们是由程序员定义而在运行时由编译器创建的,它没有自己的实例变量(这里区别于类的成员变量,他们是属于实例对象的,而不是属于类对象的,类方法是属于类对象自己的),但类对象中存着成员变量与实例方法列表。

  • 元类对象:OC 的类方法是使用元类的根本原因,因为其中存储着对应的类对象调用的方法即类方法。其他时候都倾向于隐藏元类,因此真实世界没有人发送消息给元类对象。元类的定义和创建看起来都是编译器自动完成的,无需人为干涉。要获取一个类的元类,可使用如下定义的函数:

1
Class objc_getMetaClass(const char* name); //name为类的名字

此外还有一个获取对象所属的类的函数:

1
Class object_getClass(id obj) ;

由于类对象是元类的实例,所以当传入的参数为类名时,返回的就是指向该类所属的元类的指针。