ios开发_Runtime

1.背景、定义

1.1 Apple开源的Runtime代码

1.2 Objective-C会尽可能的将编译要做的事情推迟到运行时。 Objective-C 语言不仅需要一个编译环境,同时也需要一个运行时系统(runtime)来执行编译好的代码。

1.3 对于下面的简单方法:

[receiver message];

编译器将会转化为:

objc_msgSend(receiver, selector)//无参数  
objc_msgSend(receiver, selector, arg1, arg2, ...)//有参数 

2.消息传递流程

  • 检查receiver是否为nil,如果receiver为空,则会将 selector也设置为空,直接返回到消息调用的地方,否则下一步
  • 根据SEL到当前类中查找对应的IMP,先会在cache中检索它,如果找到了就根据函数指针跳转到这个函数执行,否则下一步
  • 检索当前类对象中的方法表(method list),如找到了,加入cache中,并且就跳转到这个函数之行,否则下一步
  • 从父类中寻找,直到根类:NSObject类。找到了就将方法加入对应类的cache表中,如果找不到则进行动态方法决议上一步,仍解决不了则下一步
  • 进入消息转发上一步,仍解决不了则下一步
  • 程序崩溃

3.动态方法

+ (BOOL)resolveClassMethod:(SEL)sel __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);  
+ (BOOL)resolveInstanceMethod:(SEL)sel __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); 

这个函数分别添加实例方法实现和类方法实现
在运行时(runtime),没有找到SEL的IML时就会执行。这个函数是给类利用class_addMethod添加函数的机会。

如果实现了添加函数代码则返回YES,未实现返回NO。

4.消息转发

在消息转发之前有一次重定向的问题

- (id)forwardingTargetForSelector:(SEL)aSelector __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); 

流程到了这里,系统给了个将这个SEL转给其他对象的机会。

- (void)forwardInvocation:(NSInvocation *)anInvocation;  
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector;  

5.runtime方法

两个可能会会在这个流程需要的方法:

OBJC_EXPORT BOOL class_addMethod(Class cls, SEL name, IMP imp, const charchar *types) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); 

OBJC_EXPORT IMP class_replaceMethod(Class cls, SEL name, IMP imp, const charchar *types)  __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);   

6.注解

①SEL:方法选择器,在objc.h的定义为:

typedef struct objc_selector *SEL;

所以SEL是char*指针,代表它的方法名称

②IMP:函数指针

7.推荐

https://github.com/nicklockwood/NullSafe

8.感谢

Sam_Lau的Objective-C特性:Runtime
玉令天下博客的Objective-C Runtime
顾鹏博客的Objective-C Runtime
wangzz的Objective-C runtime

                                    杏树林研发 李莹

你可能感兴趣的:(ios,Objective-C,Runtime,ios开发)