一:RunLoop的简单介绍

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController
/**
* 1:Runloop和线程的关系:1:一一对应,主线程的runloop已经默认创建,但是子线程的需要手动创建:创建子线程的runloop: NSRunLoop *run = [NSRunLoop currentRunLoop];currentRunLoop懒加载的,在同一个子线程中创建多个runloop,则返回的都是同一个对象,因为其是懒加载模式的 2:在runloop中有多个运行模式,但是runloop只能选择一种模式运行,mode里面至少要有一个timer或者是source
2:1.获得主线程对应的runloop:NSRunLoop *mainRunLoop = [NSRunLoop mainRunLoop]; 2:获得当前线程对应的runLoop:NSRunLoop *currentRunLoop = [NSRunLoop currentRunLoop];
3:CFRunLoop:1:获得主线程对应的runloop:CFRunLoopGetMain() 2:获得当前线程对应的runLoop:CFRunLoopGetCurrent()
*
*/
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
//1.获得主线程对应的runloop
NSRunLoop *mainRunLoop = [NSRunLoop mainRunLoop]; //2.获得当前线程对应的runLoop
NSRunLoop *currentRunLoop = [NSRunLoop currentRunLoop]; NSLog(@"%p---%p",mainRunLoop,currentRunLoop);
// NSLog(@"%@",mainRunLoop); //Core
NSLog(@"%p",CFRunLoopGetMain());
NSLog(@"%p",CFRunLoopGetCurrent()); NSLog(@"%p",mainRunLoop.getCFRunLoop); //Runloop和线程的关系
//一一对应,主线程的runloop已经创建,但是子线程的需要手动创建
[[[NSThread alloc]initWithTarget:self selector:@selector(run) object:nil] start];
} //在runloop中有多个运行模式,但是runloop只能选择一种模式运行
//mode里面至少要有一个timer或者是source
-(void)run
{
//如何创建子线程对应的runLoop,currentRunLoop懒加载的
NSLog(@"%@",[NSRunLoop currentRunLoop]);
NSLog(@"%@",[NSRunLoop currentRunLoop]);
NSLog(@"run---%@",[NSThread currentThread]);
} @end

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController
/**
* 1:NSLog(@"%@",[NSRunLoop currentRunLoop]);打印当前线程的RunLoop,懒加载模式,一条线程对应一个RunLoop对象,有返回,没有创建,主线程的RunLoop默认创建,子线程的RunLoop需要手动创建,[NSRunLoop currentRunLoop],同一个线程中若是创建多个RunLoop,则返回的都是同一个RunLoop对象,一个RunLoop里会有多个mode运行模式(系统提供了5个),但运行时只能指定一个RunLoop,若是切换RunLoop,则需要退出当前的RunLoop
2:定时器NSTimer问题:1:若是创建定时器用timerWithTimeInterval,则需要手动将定时器添加到NSRunLoop中,指定的运行模式为default,但是如果有滚动事件的时候,定时器就会停止工作。解决办法:更改NSRunLoop的运行模式,UITrackingRunLoopMode界面追踪,此模式是当只有发生滚动事件的时候才会开启定时器。若是任何时候都会开启定时器: NSRunLoopCommonModes,
NSRunLoopCommonModes = NSDefaultRunLoopMode + UITrackingRunLoopMode
占用,标签,凡是添加到NSRunLoopCommonModes中的事件爱你都会被同时添加到打上commmon标签的运行模式上 3:1:scheduledTimerWithTimeInterval此方法创建的定时器默认加到了NSRunLoop中,并且设置运行模式为默认。 2:若是想在子线程开启NSRunLoop:需要手动开启:NSRunLoop *currentRunloop = [NSRunLoop currentRunLoop];等到线程销毁的时候currentRunloop对象也随即销毁。2:在子线程的定时器,需要手动加入到runloop:不要忘记调用run方法 NSRunLoop *currentRunloop = [NSRunLoop currentRunLoop]; //该方法内部自动添加到runloop中,并且设置运行模式为默认
[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES]; //开启runloop
[currentRunloop run]; /*
*
*/
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
// NSLog(@"%@",[NSRunLoop currentRunLoop]); // [self timer2];
// [NSThread detachNewThreadSelector:@selector(timer2) toTarget:self withObject:nil];
[self timer1];
} -(void)timer1
{
//1.创建定时器
NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES]; //2.添加定时器到runLoop中,指定runloop的运行模式为NSDefaultRunLoopMode
/*
第一个参数:定时器
第二个参数:runloop的运行模式
*/
// [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]; //UITrackingRunLoopMode:界面追踪
[[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode]; // NSRunLoopCommonModes = NSDefaultRunLoopMode + UITrackingRunLoopMode
//占用,标签,凡是添加到NSRunLoopCommonModes中的事件爱你都会被同时添加到打上commmon标签的运行模式上
/*
0 : <CFString 0x10af41270 [0x10a0457b0]>{contents = "UITrackingRunLoopMode"}
2 : <CFString 0x10a065b60 [0x10a0457b0]>{contents = "kCFRunLoopDefaultMode"
*/
// [[NSRunLoop currentRunLoop]addTimer:timer forMode:NSRunLoopCommonModes];
} -(void)timer2
{
NSRunLoop *currentRunloop = [NSRunLoop currentRunLoop]; //该方法内部自动添加到runloop中,并且设置运行模式为默认
[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES]; //开启runloop
[currentRunloop run];
} -(void)run
{
NSLog(@"run-----%@---%@",[NSThread currentThread],[NSRunLoop currentRunLoop].currentMode);
} @end

####1.Runloop基础知识

- 1.1 字面意思

a 运行循环

b 跑圈

- 1.2 基本作用(作用重大)

a 保持程序的持续运行(ios程序为什么能一直活着不会死)

b 处理app中的各种事件(比如触摸事件、定时器事件【NSTimer】、selector事件【选择器·performSelector···】)

c 节省CPU资源,提高程序性能,有事情就做事情,没事情就休息

- 1.3 重要说明

(1)如果没有Runloop,那么程序一启动就会退出,什么事情都做不了。

(2)如果有了Runloop,那么相当于在内部有一个死循环,能够保证程序的持续运行

(2)main函数中的Runloop

a 在UIApplication函数内部就启动了一个Runloop

该函数返回一个int类型的值

b 这个默认启动的Runloop是跟主线程相关联的

- 1.4 Runloop对象

(1)在iOS开发中有两套api来访问Runloop

a.foundation框架【NSRunloop】

b.core foundation框架【CFRunloopRef】

(2)NSRunLoop和CFRunLoopRef都代表着RunLoop对象,它们是等价的,可以互相转换

(3)NSRunLoop是基于CFRunLoopRef的一层OC包装,所以要了解RunLoop内部结构,需要多研究CFRunLoopRef层面的API(Core Foundation层面)

- 1.5 Runloop参考资料

```objc

(1)苹果官方文档

https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html

(2)CFRunLoopRef开源代码下载地址:

http://opensource.apple.com/source/CF/CF-1151.16/

```

- 1.6 Runloop与线程

1.Runloop和线程的关系:一个Runloop对应着一条唯一的线程

问题:如何让子线程不死

回答:给这条子线程开启一个Runloop

2.Runloop的创建:主线程Runloop已经创建好了,子线程的runloop需要手动创建

3.Runloop的生命周期:在第一次获取时创建,在线程结束时销毁

- 1.7 获得Runloop对象

```objc

1.获得当前Runloop对象

//01 NSRunloop

NSRunLoop * runloop1 = [NSRunLoop currentRunLoop];

//02 CFRunLoopRef

CFRunLoopRef runloop2 =   CFRunLoopGetCurrent();

2.拿到当前应用程序的主Runloop(主线程对应的Runloop)

//01 NSRunloop

NSRunLoop * runloop1 = [NSRunLoop mainRunLoop];

//02 CFRunLoopRef

CFRunLoopRef runloop2 =   CFRunLoopGetMain();

3.注意点:开一个子线程创建runloop,不是通过alloc init方法创建,而是直接通过调用currentRunLoop方法来创建,它本身是一个懒加载的。

4.在子线程中,如果不主动获取Runloop的话,那么子线程内部是不会创建Runloop的。可以下载CFRunloopRef的源码,搜索_CFRunloopGet0,查看代码。

5.Runloop对象是利用字典来进行存储,而且key是对应的线程Value为该线程对应的Runloop。

```

- 1.8 Runloop相关类

(1)Runloop运行原理图

![PNG](2.png)

(2)五个相关的类

a.CFRunloopRef

b.CFRunloopModeRef【Runloop的运行模式】

c.CFRunloopSourceRef【Runloop要处理的事件源】

d.CFRunloopTimerRef【Timer事件】

e.CFRunloopObserverRef【Runloop的观察者(监听者)】

(3)Runloop和相关类之间的关系图

![PNG](1.png)

(4)Runloop要想跑起来,它的内部必须要有一个mode,这个mode里面必须有source\observer\timer,至少要有其中的一个。

- CFRunloopModeRef

1.CFRunloopModeRef代表着Runloop的运行模式

2.一个Runloop中可以有多个mode,一个mode里面又可以有多个source\observer\timer等等

3.每次runloop启动的时候,只能指定一个mode,这个mode被称为该Runloop的当前mode

4.如果需要切换mode,只能先退出当前Runloop,再重新指定一个mode进入

5.这样做主要是为了分割不同组的定时器等,让他们相互之间不受影响

6.系统默认注册了5个mode

a.kCFRunLoopDefaultMode:App的默认Mode,通常主线程是在这个Mode下运行

b.UITrackingRunLoopMode:界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响

c.UIInitializationRunLoopMode: 在刚启动 App 时第进入的第一个 Mode,启动完成后就不再使用

d.GSEventReceiveRunLoopMode: 接受系统事件的内部 Mode,通常用不到

e.kCFRunLoopCommonModes: 这是一个占位用的Mode,不是一种真正的Mode

iOS开发RunLoop学习:一:RunLoop简单介绍的更多相关文章

  1. 李洪强iOS开发之拓展篇—UIDynamic(简单介绍)

      iOS开发拓展篇—UIDynamic(简单介绍) 一.简单介绍 1.什么是UIDynamic UIDynamic是从iOS 7开始引入的一种新技术,隶属于UIKit框架 可以认为是一种物理引擎,能 ...

  2. iOS开发基础-UITableView控件简单介绍

     UITableView 继承自 UIScrollView ,用于实现表格数据展示,支持垂直滚动.  UITableView 需要一个数据源来显示数据,并向数据源查询一共有多少行数据以及每一行显示什么 ...

  3. iOS开发多线程篇 09 —NSOperation简单介绍

    iOS开发多线程篇—NSOperation简单介绍 一.NSOperation简介 1.简单说明 NSOperation的作⽤:配合使用NSOperation和NSOperationQueue也能实现 ...

  4. 【iOS开发-80】Quartz2D画图简单介绍:直线/圆形/椭圆/方形以及上下文栈管理CGContextSaveGState/CGContextRestoreGState

    watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2Vpc3ViYW8=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA ...

  5. qt-qml移动开发之在ios上开发和部署app流程简单介绍

    qt5.3已经全面支持移动开发,除了mac,windows,linux.还支持ios,android,wp,meego等移动平台,本教程是作者依据自己的经验,从头讲怎么样在ios上公布自己的app.因 ...

  6. 关于iOS开发的学习

    关于iOS开发的学习,打个比方就像把汽车分解:    最底层的原料有塑料,钢铁    再用这些底层的东西造出来发动机,座椅    最后再加上写螺丝,胶水等,把汽车就拼起来了 iOS基本都是英文的资料, ...

  7. iOS开发架构学习记录

    闲着没事看了一些iOS开发架构的视频,简单的介绍了几个常用的架构设计,现将它记录如下,以后有时间再专门写这方面的内容,大家可以看看,感兴趣的就进一步学习. 一.架构基础 1.架构设计的目的 进一步解耦 ...

  8. iOS开发UI篇—xib的简单使用

    iOS开发UI篇—xib的简单使用 一.简单介绍 xib和storyboard的比较,一个轻量级一个重量级. 共同点: 都用来描述软件界面 都用Interface Builder工具来编辑 不同点: ...

  9. iOS开发UI篇—UIScrollView控件介绍

    iOS开发UI篇—UIScrollView控件介绍 一.知识点简单介绍 1.UIScrollView控件是什么? (1)移动设备的屏幕⼤大⼩小是极其有限的,因此直接展⽰示在⽤用户眼前的内容也相当有限 ...

  10. iOS开发UI篇—常见的项目文件介绍

    iOS开发UI篇—常见的项目文件介绍 一.项目文件结构示意图 二.文件介绍 1.products文件夹:主要用于mac电脑开发的可执行文件,ios开发用不到这个文件 2.frameworks文件夹主要 ...

随机推荐

  1. ajax跨域过程

  2. JS之字符串和数组

    字符串: 属性: length:可以获取字符串的长度: <script type="text/javascript"> var str = "haha&quo ...

  3. rman 备份并异机恢复

    1.RMAN 备份脚本 RUN { CONFIGURE RETENTION POLICY DAYS; CONFIGURE CONTROLFILE AUTOBACKUP ON; CONFIGURE CO ...

  4. 数据分析-jupyter

    安装 jupyter pip install jupyter 快捷键 插入 cell : a  b 删除cell  :  x 切换cell的模式: m  y 执行  shift +enter 查看帮助 ...

  5. Linux 桌面玩家指南:18. 我对 Docker 的使用的学习心得

    原文:Linux 桌面玩家指南:18. 我对 Docker 的使用的学习心得 特别说明:要在我的随笔后写评论的小伙伴们请注意了,我的博客开启了 MathJax 数学公式支持,MathJax 使用$标记 ...

  6. C# async/await异步编程深入理解

    异步函数简介 一般指 async 修饰符声明得.可包含await表达式得方法或匿名函数. 声明方式 异步方法的声明语法与其他方法完全一样, 只是需要包含 async 关键字.async可以出现在返回值 ...

  7. 免费css布局和模板集合

    Internet 上有很多基于 (X)HTML/CSS 标记的模板.如果你是一个 Web 开发人员,你不希望把时间一次又一次地浪费在重复代码设计上面,这里提供了一个列表,提供了基于 CSS 的免费模板 ...

  8. [Javascript] Compose multiple functions for new behavior in JavaScript

    In this lesson you will create a utility function that allows you to quickly compose behavior of mul ...

  9. jsapi微信支付v3版

    请看清楚你的微信支付是v2还是v3.在这里整理的是v3的,v2的同学请忽略! 前期准备须要用的是商户证书,用的是p12的.设置api密钥(在微信商户端中设置),还须要在微信公众号中设置jsapi授权文 ...

  10. MAC 下的简单 SHELL 入门

    1.创建文件 .sh 文件 本例,将 sh 文件全名为 demo.sh,接下来使用随意熟悉的编辑器编辑命令就可以 2.编写 .sh 文件 #!/bin/sh echo +--------------- ...