runloop和runtime

runloop

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

一个程序从main函数开始,函数执行完毕之后就会退出,iOS程序也是一样的,但是我们从没看到过iOS程序打开之后直接闪退,肯定是有一些东西阻止了程序的退出,最简单的就是添加一个死循环,RunLoop就是类似于这样的一个死循环,保证你的应用程序不被退出,区别就是RunLoop会在你的程序有事件(点击事件、摇晃事件等)要处理的时候才会去让cpu处理,在程序没有事件处理的时候就让系统cpu休眠。在iOS中,每个线程都有一个RunLoop,但是默认状态下只有主线程的RunLoop是开启的(系统自动帮我们开启),其他线程开启需要以下代码
BOOL isRunning = NO;
    while (!isRunning) {
        isRunning = [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
    }
currentRunLoop 可以获取当前线程的RunLoop , 循环是为了保证能开启RunLoop(系统繁忙时有可能开启失败)
如果用timerWithTimeInterval来创建NSTimer,我们需要把这个Timer假如到RunLoop才能执行,如果是在子线程,还需要开启这个RunLoop。

在做项目时曾遇到过两个问题,需要手动开启runLoop:
1.在一个页面中有一个轮播图和tableView。在滑动tableView的过程中,轮播图不动了。这时我是用了RunLoop将轮播图的NSTimer加入到了RunLoop中。
2.在子线程中开启了另外一个子线程用于下载图片。这时发现下载图片的代码不执行。通过在下载图片的代码里手动开启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就是运行时,一个程序开发的过程通常可以分为以下阶段,编辑-预编译-编译-连接-运行,运行时可以说就是我们的程序再运行的阶段发生的一些事情,在这个阶段程序通常会把一些OC的代码转化成C语言的代码,从而提高执行的效率,在这个阶段我们也可以动态的为某个对象的属性赋值,而对象的属性具体是什么类型也会在这个阶段进行确定(NSString *str = [NSData data]; 其中str在编译的时候是NSString类型,运行的时候是NSData类型)。系统也提供了Runtime的类库,让我们可以直接调用一些运行时把OC代码转化C之后的代码比如:objc_msgSend();同样也可以通过运行时,为分类添加属性,需要用到objc_getAssociatedObject和objc_setAssociatedObject函数。

原文地址:https://www.cnblogs.com/menglingxu/p/5732515.html