Class
文件:objc.h
Class
是一个 objc_class
类型的结构体指针,也就是类。id
是 objc_object
类型的指针。如下:
1 | #if !OBJC_TYPES_DEFINED |
objc_class
定义如下:
1 | struct objc_class { |
由此可见,类也是一个对象。也就是说类和对象都是对象,分别被称为 类对象
、实例对象
。
isa
:objc_object
(实例对象)中的 isa
指针指向类的结构体称为 class
(也就是该对象所属的类)。其中存放着普通成员变量与动态方法实例方法(“-“开头)。objc_class
中的 isa
指针指向类结构体称之为 metaclass
,其中存放着 static
类型的成员变量与 static
类型的方法(“+” 开头的方法)。
一图胜千言:
所有实例对象的 isa
指针都指向它所属的类,所属的类的 isa
指针指向其 metaclass
。所有的 metaclass
都指向其之神。root metaclass
是通过继承根类产生的,与根 class 结构体成员一致,不同的是root metaclass
的 isa
指针指向自身。
Objective-C 中的元素
SEL
SEL
是 selector
在 Objective-C 中的表示类型。selector
可以理解为区别方法的 ID。
1 | typedef struct objc_selector *SEL; |
其定义如下:
1 | struct objc_selector { |
IMP
IMP
是编译器生成的函数指针。该类型决定调用具体函数的实现。
其定义如下:
1 | /// A pointer to the function of a method implementation. |
Method
Method
代表类中的某个方法的类型。
1 | typedef struct objc_method *Method; |
其定义如下:
1 | struct objc_method { |
Ivar
Ivar
代表类中实例变量的类型。
1 | typedef struct objc_ivar *Ivar; |
其定义如下:
1 | struct objc_ivar { |
objc_property_t
objc_property_t
是内置类型属性,其定义如下:
1 | typedef struct objc_property *objc_property_t; |
还有一个关联属性 objc_property_attribute_t
类型,它是属性的 attribute
,包含属性名称、属性编码类型、原子类型/非原子类型等。其定义如下:
1 | typedef struct { |
Cache
Cache
:缓存方法表
1 | typedef struct objc_cache *Cache |
其定义如下:
1 | struct objc_cache { |
Catagory
Catagory
:可以动态为已经存在的类添加新的方法。
1 | typedef struct objc_category *Category; |
其定义如下:
1 | struct objc_category { |
消息传递
在 Objective-C 中,调用某个方法,相当于发送一条消息。会调用 runtime 模块中的 objc_msgSend
函数调用,比如 [self someMethod];
方法,会转换成 objc_msgSend(self, someMethod)
。
消息调用类型还包括以下几种:
- objc_msgSend_stret:如果带发送的消息返回结构体,可交由此函数处理。
- objc_msgSend_fpret:消息返回浮点数,
- objc_msgSend_Super:给父类发送消息,如 [super message:parameter]
更多解释可以查看这里
消息转发
第一步:通过 resolveInstanceMethod:
方法决定是否能在本类中动态添加方法,返回 YES 可以通过 class_addMethod
来动态添加方法,消息得到处理。如果返回 NO,则会启动将消息转发给其他对象。
第二步:通过 forwardingTargetForSelector:
,当前接收者有第二次机会处理这个未知的消息,runtime 会询问能否将消息转给其他的接收者来处理。如果返回某个对象则会调用对象的方法,然后结束。反之返回 nil,则进入第三步。
第三步:通过 methodSignatureForSelector:
方法签名,如果返回 nil,则消息无法处理。如果返回 methodSignature
则进入下一步。
第四步:通过 forwardInvocation:
方法,可以通过 NSInvocation
对象做很多处理,比如修改方法的实现,修改响应对象等。如果方法调用成功,则结束。如果失败,则调用 doesNotRecognizeSelector
方法,如果没有实现这个方法,则程序会崩溃。
完整流程图:
地方