iOS RunLoop 的个人理解

2024-04-17 09:32
文章标签 理解 ios 个人 runloop

本文主要是介绍iOS RunLoop 的个人理解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

2017-5-17 周四 晴  作者:58婚恋技术部

一,RunLoop 部分
启动 run loop 只对程序的辅助线程有意义。一个 run loop 通常必须包含一个输 入源或定时器来监听事件,如果一个都没有 ,run loop 启动后立即退出。每个线程都有一个或多个 run loop, 主线程的 runloop 默认是打开的,而子线程的 runloop 则默认是关闭的,需要人为去打开,也就是执行 run() 方法。 cocoa 中的 runloop 是非线程安全的,不能跨线程操作其他线程的 runloop ,而 core fundation 中的 runloop 是线程安全的,可以通过调用 getCFRunloop 方法得到对应的 core fundtion runloop 已达到线程安全的目的。
由于 runloop 并非全自动的,所以我们需要通过 while/for 语句来驱动 runloop 能够循环运行,比如如下代码:

BOOL isRunning = NO;
do {
isRunning =
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate: [NSDate distantFuture]
];
} while (isRunning);
但是上面代码有几个疑问,
问题一,就是用什么来触发 runloop 结束?
答案是这样的, runMode 方法是在当前 runloop 中在给定的时间内等待一个输入源,而输入源有两种,一个是 port 的方式,一个是 performSelector 的方式,所以上面这个等待输入源的 runloop 在接到其他线程 perform 过来的 selector 就可以运行结束了。


问题二,为什么这个 runloop 只接受一个词 perform 就结束呢?而不是可以一直在这接受 perform
这个方法的作用就是只运行一次,直到一个指定时间或者有输入源时结束,所以 runloop 一般需要配合 while 等循环体使用,才能循环监听输入源


问题三,如何在一个子线程里面创建一个 runloop 并且运行他?
每个线程都会自动创建 runloop ,只是没有启动而已,我们 [NSRunLoop getCurrentRunLoop] 就可以得到当前线程的 runloop ,执行 run 方法就可以启动 runloop


问题四,一个 runloop 为什么会阻塞线程?

runloop
的概念本来就是一个黑洞,当线程运行到这个 runloop 中时就会把对应 mode 的资源交给 runloop ,这个时候 runloop 就会去处理对应的输入源或者定时源事件,程序进入 runloop 就会进入 runloop 的生命周期,该线程下 runloop 外面的代码不会执行,除非 runloop 结束,就会继续往下执行。所以这个 mode 就把事件进行了分类,有 default connect tracking 等等,


二,perform  Selector的实际意义 下面方法定义在 nsobject 中,是可以在其他线程中执行的 seelctor ,并非是创建新线程,而是线程之间通讯,这个方法会触发另外一个线程的输入源, runloop 若运行就会检测的到
=================================
performSelectorOnMainThread:withObject:waitUntilDone:
performSelectorOnMainThread:withObject:waitUntilDone:modes:          //modes
是指 runloop 的模型


performSelector:onThread:withObject:waitUntilDone:
performSelector:onThread:withObject:waitUntilDone:modes:

performSelector:withObject:afterDelay:
performSelector:withObject:afterDelay:inModes:

cancelPreviousPerformRequestsWithTarget://
取消掉《 performSelector:withObject:afterDelay:

cancelPreviousPerformRequestsWithTarget:selector:object:
疑问,
1,cocoa的runloop是非线程安全的,那么 perform这种通讯机制明显在cocoa中完成,为什么又没有问题呢?
答案:
一,是因为performSelector一个消息到其他线程时,其他线程的runloop并没有启动,
二,runloop若启动了,就要把对应的mode传过去,mode的获取方法是通过getCFRunloopMode方法得到。

三,runloop
的生命周期
==================================
 Run loop
入口
kCFRunLoopEntry
 Run loop
何时处理一个定时器
kCFRunLoopBeforeTimers
 Run loop
何时处理一个输入源

 Run loop
何时进入睡眠状态

 Run loop
何时被唤醒 , 但在唤醒之前要处理的事件

 Run loop
终止

四,NSRunLoop 基本方法 ============================= 每个线程都会有一个 runloop ,这个 runloop 在干什么用呢,

NSRunLoop *timerRunLoop =
[NSRunLoop mainRunLoop] ;// 得到 mainrunloop [timerRunLoop addTimer:timer forMode:] // timer 添加到 timerRunloop 中,

NSString* runLoopMode =
[[NSRunLoop currentRunLoop] currentMode];// 得到当前线程
runloop

[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate: [NSDate distantFuture] ];// 这个方法会等待一个输入源,

比较实用的例子如下:

NSThread *runLoopThread =
[[NSThread alloc]
initWithTarget:self selector:@selector(handleRunLoopThreadTask) object:nil];
[runLoopThread start]
;
使用 Run Loop ,在线程执行期间, handleNormalButtonTouchUpInside 能够正常输入信息

while (!self.normalThreadDidFinishFlag) {
NSLog(@"Begin RunLoop");
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate: [NSDate distantFuture]
];
NSLog(@"End RunLoop");
}
在线程的这个方法 handleRunLoopThreadTask 执行完了之后实用 performSelectorOnmainThread 来设置 self.normalThreadDidFinishFlag 的值结束
runMode


五,runloop
需要注意的事项
runloop 添加到 mainThread mainRunLoop 中,就会出现卡死情况,因为阻塞了主线程,正常的做法是在 operation 中做,或者 NSThread 中做 runloop 的添加动作,在执行方法中再 perform 到其他 thread 中执行对应的 method


为了创建一 run loop 观察者 , 你可以创建一个 CFRunLoopObserverRef 类型的实例

run Loop
在处理输入事件时会产生通知,可以通过 Core Foundation 向线程中添加 run-loop observers 来监听特定事件,(这个怎么实现?)


六,runloop
的使用场景 =
====================================
Run loop
在你要和线程有更多的交互时才需要 , 比如以下情况
:
 
使用端口或自定义输入源来和其他线程通信

 
使用线程的定时器

 Cocoa
中使用任何 performSelector... 的方法

 
使线程周期性工作 铁友火车票 ios native lua 交互部分就是用的 runloop 控制整个流程


Run loop
对象提供了添加输入源 , 定时器和 run loop 的观察者以及启动 run loop 的接口
每个线程都有唯一的与之关联的 run loop 对象。在 Cocoa , 该对象是 NSRunLoop 类的一个实例


七, 获得 runloop ===================( 没走通)
===============
//
把当前监听 netserviece 的输入源加入到 runloop ,然后移除

    NSNetService *service =
[[NSNetService alloc] initWithDomain:@"local" type:@"_crypttest._tcp" name: [[UIDevice currentDevice]
name] port:55663];
   
[service publish] ;// 通知接收者

    CFReadStreamRef readStream = NULL;
    CFReadStreamSetProperty(readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
   
[readStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSRunLoopCommonModes];
   
[readStream removeFromRunLoop:[NSRunLoop currentRunLoop]
forMode:NSRunLoopCommonModes];
//runloop
中添加
timer
    NSDate *fireDate =
[NSDate dateWithTimeIntervalSinceNow:5.0]
;
    NSTimer *cameraTimer =
[[NSTimer alloc]
initWithFireDate:fireDate interval:1.0 target:self selector:@selector(timedPhotoFire) userInfo:nil repeats:YES];
   
[[NSRunLoop mainRunLoop]
addTimer:cameraTimer forMode:NSDefaultRunLoopMode];
    self.cameraTimer = cameraTimer;
        //
注意 timer 要释放

    if (
[self.cameraTimer isValid]
)
    {
       
[self.cameraTimer invalidate]
;
    }
//

八,runloopMode
的种类
==================================
1) NSDefaultRunLoopMode:
大多数工作中默认的运行方式。

2) NSConnectionReplyMode:
使用这个 Mode 去监听 NSConnection 对象的状态,我们很少需要自己使用这个 Mode

3) NSModalPanelRunLoopMode:
使用这个 Mode Model Panel 情况下去区分事件 (OS X 开发中会遇到 )

4) UITrackingRunLoopMode:
使用这个 Mode 去跟踪来自用户交互的事件(比如 UITableView 上下滑动)。

5) GSEventReceiveRunLoopMode:
用来接受系统事件,内部的 Run Loop Mode

6) NSRunLoopCommonModes:
这是一个伪模式,其为一组 run loop mode 的集合。如果将 Input source 加入此模式,意味着关联 Input source Common Modes 中包含的所有模式下。在 iOS 系统中 NSRunLoopCommonMode 包含 NSDefaultRunLoopMode NSTaskDeathCheckMode UITrackingRunLoopMode. 可使用 CFRunLoopAddCommonMode 方法向 Common Modes 中添加自定义 mode


九,两个实际问题(没有实际验证过)

1,如何在后台线程运行NSURLConnection====== http://wufawei.com/2013/05/use-NSRunLoop/

2,解决NSURLConnection在用户滚动UIScrollView或者UITableView不执行的问题 。===== http://wufawei.com/2013/05/use-NSRunLoop/

========================runloop 拓展阅读
==================================
http://blog.csdn.net/wzzvictory/article/details/9237973
http://chun.tips/blog/2014/10/20/zou-jin-run-loopde-shi-jie-%5B%3F%5D-:shi-yao-shi-run-loop%3F/
http://chun.tips/blog/2014/10/20/zou-jin-run-loopde-shi-jie-er-:ru-he-pei-zhi-run-loop-sources/

这篇关于iOS RunLoop 的个人理解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/911421

相关文章

一文带你理解Python中import机制与importlib的妙用

《一文带你理解Python中import机制与importlib的妙用》在Python编程的世界里,import语句是开发者最常用的工具之一,它就像一把钥匙,打开了通往各种功能和库的大门,下面就跟随小... 目录一、python import机制概述1.1 import语句的基本用法1.2 模块缓存机制1.

深入理解C语言的void*

《深入理解C语言的void*》本文主要介绍了C语言的void*,包括它的任意性、编译器对void*的类型检查以及需要显式类型转换的规则,具有一定的参考价值,感兴趣的可以了解一下... 目录一、void* 的类型任意性二、编译器对 void* 的类型检查三、需要显式类型转换占用的字节四、总结一、void* 的

深入理解Redis大key的危害及解决方案

《深入理解Redis大key的危害及解决方案》本文主要介绍了深入理解Redis大key的危害及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着... 目录一、背景二、什么是大key三、大key评价标准四、大key 产生的原因与场景五、大key影响与危

深入理解C++ 空类大小

《深入理解C++空类大小》本文主要介绍了C++空类大小,规定空类大小为1字节,主要是为了保证对象的唯一性和可区分性,满足数组元素地址连续的要求,下面就来了解一下... 目录1. 保证对象的唯一性和可区分性2. 满足数组元素地址连续的要求3. 与C++的对象模型和内存管理机制相适配查看类对象内存在C++中,规

认识、理解、分类——acm之搜索

普通搜索方法有两种:1、广度优先搜索;2、深度优先搜索; 更多搜索方法: 3、双向广度优先搜索; 4、启发式搜索(包括A*算法等); 搜索通常会用到的知识点:状态压缩(位压缩,利用hash思想压缩)。

安卓链接正常显示,ios#符被转义%23导致链接访问404

原因分析: url中含有特殊字符 中文未编码 都有可能导致URL转换失败,所以需要对url编码处理  如下: guard let allowUrl = webUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {return} 后面发现当url中有#号时,会被误伤转义为%23,导致链接无法访问

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言

【C++高阶】C++类型转换全攻略:深入理解并高效应用

📝个人主页🌹:Eternity._ ⏩收录专栏⏪:C++ “ 登神长阶 ” 🤡往期回顾🤡:C++ 智能指针 🌹🌹期待您的关注 🌹🌹 ❀C++的类型转换 📒1. C语言中的类型转换📚2. C++强制类型转换⛰️static_cast🌞reinterpret_cast⭐const_cast🍁dynamic_cast 📜3. C++强制类型转换的原因📝

深入理解RxJava:响应式编程的现代方式

在当今的软件开发世界中,异步编程和事件驱动的架构变得越来越重要。RxJava,作为响应式编程(Reactive Programming)的一个流行库,为Java和Android开发者提供了一种强大的方式来处理异步任务和事件流。本文将深入探讨RxJava的核心概念、优势以及如何在实际项目中应用它。 文章目录 💯 什么是RxJava?💯 响应式编程的优势💯 RxJava的核心概念

如何通俗理解注意力机制?

1、注意力机制(Attention Mechanism)是机器学习和深度学习中一种模拟人类注意力的方法,用于提高模型在处理大量信息时的效率和效果。通俗地理解,它就像是在一堆信息中找到最重要的部分,把注意力集中在这些关键点上,从而更好地完成任务。以下是几个简单的比喻来帮助理解注意力机制: 2、寻找重点:想象一下,你在阅读一篇文章的时候,有些段落特别重要,你会特别注意这些段落,反复阅读,而对其他部分