Runtime和Runloop的区别

一.RunLoop:

Runloop是事件接收和分发机制的一个实现。

Runloop提供了一种异步执行代码的机制,不能并行执行任务。

在主队列中,Main RunLoop直接配合任务的执行,负责处理UI事件、定时器以及其他内核相关事件。

(1).RunLoop的主要目的:

保证程序执行的线程不会被系统终止。

(2).什么时候使用Runloop ?

当需要和该线程进行交互的时候才会使用Runloop.

每一个线程都有其对应的RunLoop,但是默认非主线程的RunLoop是没有运行的,需要为RunLoop添加至少一个事件源,然后去run它。

一般情况下我们是没有必要去启用线程的RunLoop的,除非你在一个单独的线程中需要长久的检测某个事件。

主线程默认有Runloop。当自己启动一个线程,如果只是用于处理单一的事件,则该线程在执行完之后就退出了。所以当我们需要让该线程监听某项事务

时,就得让线程一直不退出,runloop就是这么一个循环,没有事件的时候,一直卡着,有事件来临了,执行其对应的函数。

RunLoop,正如其名所示,是线程进入和被线程用来相应事件以及调用事件处理函数的地方.需要在代码中使用控制语句实现RunLoop的循环,也就是说,需要代码提供while或者for循环来驱动RunLoop.

在这个循环中,使用一个runLoop对象[NSRunloop currentRunloop]执行接收消息,调用对应的处理函数.

Runloop接收两种源事件:input sources和timer sources。

input sources 传递异步事件,通常是来自其他线程和不同的程序中的消息;

timer sources(定时器) 传递同步事件(重复执行或者在特定时间上触发)。

除了处理input sources,Runloop

也会产生一些关于本身行为的notificaiton。注册成为Runloop的observer,可以接收到这些notification,做一些额外

的处理。(使用CoreFoundation来成为runloop的observer)。

Runloop工作的特点:

1>当有时间发生时,Runloop会根据具体的事件类型通知应用程序作出相应;

2>当没有事件发生时,Runloop会进入休眠状态,从而达到省电的目的;

3>当事件再次发生时,Runloop会被重新唤醒,处理事件.

提示:一般在开发中很少会主动创建Runloop,而通常会把事件添加到Runloop中.

二.Runtime:

RunTime简称运行时。就是系统在运行的时候的一些机制,其中最主要的是消息机制。对于C语言,函数的调用在编译的时候会决定调用哪个函数(

C语言的函数调用请看这里

)。编译完成之后直接顺序执行,无任何二义性。OC的函数调用成为消息发送。属于动态调用过程。在编译的时候并不能决定真正调用哪个函数(事实证明,在编

译阶段,OC可以调用任何函数,即使这个函数并未实现,只要申明过就不会报错。而C语言在编译阶段就会报错)。只有在真正运行的时候才会根据函数的名称找

到对应的函数来调用。

那OC是怎么实现动态调用的呢?下面我们来看看OC通过发送消息来达到动态调用的秘密。假如在OC中写了这样的一个代码:

[objc] view plain?

<span style="font-size:18px;">[obj makeText];</span>

其中obj是一个对象,makeText是一个函数名称。对于这样一个简单的调用。在编译时RunTime会将上述代码转化成

[objc] view plain?

objc_msgSend(obj,@selector(makeText));

首先我们来看看obj这个对象,iOS中的obj都继承于NSObject。

[objc] view plain?

@interface NSObject <nsobject> {

Class isa  OBJC_ISA_AVAILABILITY;

}</nsobject>

在NSObjcet中存在一个Class的isa指针。然后我们看看Class:

[objc] view plain?

typedef struct objc_class *Class;

struct objc_class {

Class isa; // 指向metaclass

Class super_class ; // 指向其父类

const charchar *name ; // 类名

long version ; // 类的版本信息,初始化默认为0,可以通过runtime函数class_setVersion和class_getVersion进行修改、读取

long info; // 一些标识信息,如CLS_CLASS (0x1L) 表示该类为普通 class ,其中包含对象方法和成员变量;CLS_META (0x2L) 表示该类为 metaclass,其中包含类方法;

long instance_size ; // 该类的实例变量大小(包括从父类继承下来的实例变量);

struct objc_ivar_list *ivars; // 用于存储每个成员变量的地址

struct objc_method_list **methodLists ; // 与 info 的一些标志位有关,如CLS_CLASS (0x1L),则存储对象方法,如CLS_META (0x2L),则存储类方法;

struct objc_cache *cache; // 指向最近使用的方法的指针,用于提升效率;

struct objc_protocol_list *protocols; // 存储该类遵守的协议

}

我们可以看到,对于一个Class类中,存在很多东西,下面我来一一解释一下:

Class

isa:指向metaclass,也就是静态的Class。一般一个Obj对象中的isa会指向普通的Class,这个Class中存储普通成员变量和对

象方法(“-”开头的方法),普通Class中的isa指针指向静态Class,静态Class中存储static类型成员变量和类方法(“+”开头的方

法)。

Class super_class:指向父类,如果这个类是根类,则为NULL。

下面一张图片很好的描述了类和对象的继承关系:

注意:所有metaclass中isa指针都指向跟metaclass。而跟metaclass则指向自身。

Root metaclass是通过继承Root class产生的。与root class结构体成员一致,也就是前面提到的结构。不同的是Root

metaclass的isa指针指向自身。

Class类中其他的成员这里就先不做过多解释了,下面我们来看看:

@selector (makeText):

这是一个SEL方法选择器。SEL其主要作用是快速的通过方法名字(makeText)查找到对应方法的函数指针,然后调用其函数。SEL其本身是一个

Int类型的一个地址,地址中存放着方法的名字。对于一个类中。每一个方法对应着一个SEL。所以iOS类中不能存在2个名称相同的方法,即使参数类型不

同,因为SEL是根据方法名字生成的,相同的方法名称只能对应一个SEL。

下面我们就来看看具体消息发送之后是怎么来动态查找对应的方法的。

首先,编译器将代码[obj makeText];转化为objc_msgSend(obj, @selector

(makeText));,在objc_msgSend函数中。首先通过obj的isa指针找到obj对应的class。在Class中先去cache中

通过SEL查找对应函数method(猜测cache中method列表是以SEL为key通过hash表来存储的,这样能提高函数查找速度),若

cache中未找到。再去methodList中查找,若methodlist中未找到,则取superClass中查找。若能找到,则将method加

入到cache中,以方便下次查找,并通过method中的函数指针跳转到对应的函数中去执行。

时间: 2024-08-01 09:56:44

Runtime和Runloop的区别的相关文章

iOS runtime和runloop

runtime 和 runloop 作为一个程序员进阶是必须的,也是非常重要的, 在面试过程中是经常会被问到的, 所以大家有必要进行研究,有能力的童鞋可以和下面作者一样, 亲历实践一下. 在简书里发现了两篇非常好的文章介绍 runtime和runloop的,在这里合二为一了, 把原版作者的东西拿了过来, 为了尊重作者,在这里注明一下 @sam_lau 是runtime的作者, @tripleCC是runloop的作者   RunTime Objective-C是基于C语言加入了面向对象特性和消息

字典转模型KVC和runtime二者实现与区别

我们知道在开发中,字典转模型是一种很常用的设计模式,当字典中元素的个数比较少的时候,我们可以直接用dic[key]去给模型对象的属性赋值,但是当字典中元素的个数比较多的时候,再用前面的解决方法就不行了,所以就有了KVC(key value coding:键值编码)字典转模型的设计模式. KVC的设计原理: [item setValue:@"value" forKey:@"property"]: 1.首先去模型中查找有没有setProperty,找到,直接调用赋值 [

runtime和runloop的个人理解

RunTime简称运行时.就是系统在运行的时候的一些机制,其中最主要的是消息机制.对于C语言,函数的调用在编译的时候会决定调用哪个函数( C语言的函数调用请看这里 ).编译完成之后直接顺序执行,无任何二义性.OC的函数调用成为消息发送.属于动态调用过程.在编译的时候并不能决定真正调用哪个函数(事实证明,在编译阶段,OC可以调用任何函数,即使这个函数并未实现,只要申明过就不会报错.而C语言在编译阶段就会报错).只有在真正运行的时候才会根据函数的名称找到对应的函数来调用. 没有runloop程序就启

NSURLConnection和Runloop(面试)

(1)两种为NSURLConnection设置代理方式的区别 //第一种设置方式: //通过该方法设置代理,会自动的发送请求 // [[NSURLConnection alloc]initWithRequest:request delegate:self]; //第二种设置方式: //设置代理,startImmediately为NO的时候,该方法不会自动发送请求 NSURLConnection *connect = [[NSURLConnection alloc]initWithRequest:

ios开发网络学习六:设置队列请求与RunLoop

#import "ViewController.h" @interface ViewController ()<NSURLConnectionDataDelegate> @end @implementation ViewController -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [self newThreadDelegate2]; } -(void

iOS开发中的重要知识点

1.动态特性 2.内存管理 3.block 4.单例.代理.协议.分类 5.Runtime 6.Runloop 7.响应者链条 8.KVC/KVO 9.View.Layer.Window之间的关系和原理 10.TableView.WebView 11.生命周期和继承链 12.GCD 13.网络协议 14.XML和JSON解析 15.加密解密 16.数据持久化和FMDB 17.SD底层.了解Kingfisher 18.AFN底层.了解Alamofire 19.Masonry.了解SnapKit 2

Objective-C Category 的实现原理[转]

对设计模式有一定了解的朋友应该听说过装饰模式,Objective-C 中的 Category 就是对装饰模式的一种具体实现.它的主要作用是在不改变原有类的前提下,动态地给这个类添加一些方法.在 Objective-C 中的具体体现为:实例(类)方法.属性和协议.是的,在 Objective-C 中可以用 Category 来实现协议.本文将结合 runtime(我下载的是当前的最新版本 objc4-646.tar.gz) 的源码来探究它实现的原理. 使用场景 根据苹果官方文档对 Category

Linux电源管理(2)_Generic PM之基本概念和软件架构(蜗窝科技,www.wowotech.net)

1. 前言 这里的Generic PM,是蜗蜗自己起的名字,指Linux系统中那些常规的电源管理手段,包括关机(Power off).待机(Standby or Hibernate).重启(Reboot)等.这些手段是在嵌入式Linux普及之前的PC或者服务器时代使用的.在那个计算机科学的蛮荒时代,人类在 摩尔定律的刺激下,孜孜追求的是计算机的计算能力.处理性能,因此并不特别关心Power消耗. 在这种背景下发展出来的Linux电源管理机制,都是粗放的.静态的.被动的,具体请参考下面的介绍. 2

GCD API 理解 (一)

资料先行 GCD 深入理解:第一部分 GCD 深入理解:第二部分 以上两篇文章是关于GCD讲的比较好的文章,翻译自raywenderlich,该网站有很多关于iOS 开发的优秀文章. 引子 iOS 开发中有三大进阶性的技术点,分别是GCD.runtime 和runloop.其中GCD用的最多,runtime也有不少使用场景,runloop在系统的API里体现的比较多,项目里实际使用比较少. 一直都想就这三个技术点做一些总结,没事的时候可以回来复习巩固一下,可是记录了很多要写的点,但是文章却是一拖