iOS开发

Runtime知识梳理

2015-11-18  本文已影响141人  barrylyl

补一下:runtime使用DEMO

以前对runtime的使用和了解都很模糊。这段时间,把runtime机制好好学习、整理了一下。

##什么是runtime

runtime是一套比较底层的纯C语言API,属于1个C语言库,包含了很多底层的C语言API。

##runtime对Objective-C影响

Objective-C之所以是一个动态语言,可以动态得创建类和对象、进行消息传递和转发。正因为它拥有`Runtime`这个了不起的库。

(ps:静态语言:它的数据类型是在编译期间检查的,编写时必须申明所有变量的数据类型)

##runtime核心—消息传递

Objective-C中对象调用某个方法,它不像静态语言,在编译时就已经决定在某块内存中执行函数方法,而是在运行时给obj对象发送一条方法消息,runtime会根据对象能否对这条消息作出响应给出不同处理方式。

因为在编写Objective-C函数调用时,都会被转换成一个C的函数调用:`-objc_msgSend()`

```例:

[person work] => objc_msgSend(person, @selector(work))

```

###消息传递的执行过程

`runtime.h`头文件中,我们可以看出,OC中的类,对象以及方法其实都是一个C的结构体。

objcStruct methodStruct

`IMP:即函数指针,为方法具体实现代码块地址`

下面我们通过一个流程图来看看`objc_mgSend`传递过程中做了什么。

`[obj work]`为例:

search_IMP

####objc_cache作用

流程图这种执行方式效率较低。因为一个class方法列表中的方法,我们可能常常连一半也用不到,而每个消息都需要遍历一边`objc_method_list`这样消耗很大 。所以我们使用`objc_cache`,在找到 `method` 之后,把 `method_imp` 对应 `method_name` 利用键值存储起来。下次再接收到 `method` 消息时,可以直接在 `cache` 中查询使用。

##runtime之动态方法解析和消息转发

####如果流程图过程中,我们最终还是没有找到`work_imp`,那么我们的程序将面临崩溃,这时`runtime` 还给我们提供了动态添加方法的补救措施。

-Runtime提供了三种方式来将原来的方法实现代替掉。

####1.`Method Resolution`: 当 `Runtime` 系统在Cache和方法分发表中(包括超类)找不到要执行的方法时,`Runtime`会调用 `resolveInstanceMethod:`或`resolveClassMethod:`来给程序员一次动态添加方法实现的机会。我们需要用`class_addMethod`函数完成向特定类添加特定方法实现的操作

由于`Method Resolution`不能像消息转发那样可以交给其他对象来处理,所以只适用于在原来的类中代替掉。

```

+ (BOOL)resolveInstanceMethod:(SEL)aSEL

{

if (aSEL == @selector(method)) {

 class_addMethod([self class], @selector(method), (IMP)method, "v@:");

 return YES;

}

 return [super resolveInstanceMethod:aSEL];

}```

####2. `Fast Forwarding`: 它可以将消息处理转发给其他对象,使用范围更广,不只是限于原来的对象。

```

- (id)forwardingTargetForSelector:(SEL)aSEL

{

if(aSelector == @selector(method:)){

return alternateObject;

}

return [super forwardingTargetForSelector:aSEL];

}```

如果此方法返回nil或self,则会进入消息转发机制(forwardInvocation:);否则将向返回的对象重新发送消息。

####3. `Normal Forwarding`: 它跟Fast Forwarding一样可以消息转发,但它能通过NSInvocation对象获取更多消息发送的信息,例如:target、selector、arguments和返回值等信息。

```

- (void)forwardInvocation:(NSInvocation *)anInvocation {

SEL selector = [anInvocation selector];

newClass *Obj = [newClass new];

if ([mobile respondsToSelector:selector]) {

[anInvocation invokeWithTarget:Obj];

}

}```

DynamicMethodResolution

##runtime的一些使用 

-获取类的属性列表

-获取类的方法列表

-获取类的协议列表

-获取类的成员变量列表

-动态添加成员变量

-动态添加属性

-自动归档/解档

详细使用DEMO演示:

上一篇下一篇

猜你喜欢

热点阅读