问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

NSRunLoop RunLoopMode怎么理解

发布网友 发布时间:2022-05-18 17:24

我来回答

1个回答

热心网友 时间:2023-10-21 01:15

1.NSRunLoop是消息机制的处理模式
NSRunLoop的作用在于有事情做的时候使的当前NSRunLoop的线程工作,没有事情做让当前NSRunLoop的线程休眠

2.nstimer默认添加到当前NSRunLoop中,也可以手动制定添加到自己新建的NSRunLoop的中

[NSTimer schledTimerWithTimeInterval: target:selector:userInfo:repeats];
此方法默认添加到当前NSRunLoop中

NSTimer *timer = [NSTimer timerWithTimeInterval: invocation:repeates:];
NSTimer *timer = [[NSTimer alloc] initWithFireDate:...];

创建timer [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
注意 timer的释放

3.NSRunLoop就是一直在循环检测,从线程start到线程end,检测inputsource(如点击,双击等操作)同步事件,检测timesource同步事件,检测到输入源会执行处理函数,首先会产生通知,corefunction向线程添加runloop observers来监听事件,意在监听事件发生时来做处理。

4.runloopmode是一个集合,包括监听:事件源,定时器,以及需通知的runloop observers
模式包括:
default模式:几乎包括所有输入源(除NSConnection) NSDefaultRunLoopMode模式

mode模式:处理modal panels
connection模式:处理NSConnection事件,属于系统内部,用户基本不用
event tracking模式:如组件拖动输入源 UITrackingRunLoopModes 不处理定时事件
common modes模式:NSRunLoopCommonModes 这是一组可配置的通用模式。将input sources与该模式关联则同时也将input sources与该组中的其它模式进行了关联。

每次运行一个run loop,你指定(显式或隐式)run loop的运行模式。当相应的模式传递给run loop时,只有与该模式对应的input sources才被监控并允许run loop对事件进行处理(与此类似,也只有与该模式对应的observers才会被通知)

例:
1).在timer与table同时执行情况,当拖动table时,runloop进入UITrackingRunLoopModes模式下,不会处理定时事件,此时timer不能处理,所以此时将timer加入到NSRunLoopCommonModes模式(addTimer forMode)
2).在scroll一个页面时来松开,此时connection不会收到消息,由于scroll时runloop为UITrackingRunLoopModes模式,不接收输入源,此时要修改connection的mode
[scheleInRunLoop:[NSRunLoop currentRunLoop]forMode:NSRunLoopCommonModes];

5.关于-(BOOL)runMode:(NSString *)mode beforeDate:(NSDate *)date;方法
指定runloop模式来处理输入源,首个输入源或date结束退出。
暂停当前处理的流程,转而处理其他输入源,当date设置为[NSDate distantFuture](将来,基本不会到达的时间),所以除非处理其他输入源结束,否则永不退出处理暂停的当前处理的流程。

6.while(A){
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];

}
当前A为YES时,当前runloop会一直接收处理其他输入源,当前流程不继续处理,出为A为NO,当前流程继续

7.perform selector在thread中被序列化执行,这样就缓和了许多在同一个thread中运行多个方法所产生的同步问题。perform selector source在运行完selector后自动从run loop中移除。
当在非main thread中perform selector时,其thread中必须有一个激活的run loop。对于你自己创建的thread而言,只有你的代码显式的运行一个run loop后该perform selector才能得到执行。Run loop在当loop运行时处理所有已排队的perform selector,而不是在一个loop循环时只处理某一个perform selector。

8.performSelector关于内存管理的执行原理是这样的执行 [self performSelector:@selector(method1:) withObject:self.tableLayer afterDelay:3]; 的时候,系统会将tableLayer的引用计数加1,执行完这个方法时,还会将tableLayer的引用计数减1,由于延迟这时tableLayer的引用计数没有减少到0,也就导致了切换场景dealloc方法没有被调用,出现了内存泄露。
利用如下函数:
[NSObject cancelPreviousPerformRequestsWithTarget:self]
当然你也可以一个一个得这样用:
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(method1:) object:nil]
加上了这个以后,顺利地执行了dealloc方法

在touchBegan里面
[self performSelector:@selector(longPressMethod:) withObject:nil afterDelay:longPressTime]
然后在end 或cancel里做判断,如果时间不够长按的时间调用:
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(longPressMethod:) object:nil]
取消began里的方法

**********************************以下是我在cocoachina中看到的一份总结 转载过来
线程实现的几种方式:
1. Operation Objects // NSOperation及相关子类
2. ***** // dispatch_async等相关函数
3. Idle-time notifications // NSNotificationQueue,低优先级
3. Asynchronous functions // 异步函数
4. Timers // NSTimer
5. Separate processes // 没用过

线程创建的成本:
kernel data structures 约1KB
Stack space 512KB(secondary threads)
1MB(iOS main thread)
Creation time 约90 microseconds

Run Loop和线程的关系:
1. 主线程的run loop默认是启动的,用于接收各种输入sources
2. 对第二线程来说,run loop默认是没有启动的,如果你需要更多的线程交互则可以手动配置和启动,如果线程执行一个长时间已确定的任务则不需要。

Run Loop什么情况下使用:
a. 使用ports 或 input sources 和其他线程通信 // 不了解
b. 在线程中使用timers // 如果不启动run loop,timer的事件是不会响应的
c. 在Cocoa 应用中使用performSelector...方法 // 应该是performSelector...这种方法会启动一个线程并启动run loop吧
d. 让线程执行一个周期性的任务 // 如果不启动run loop, 线程跑完就可能被系统释放了

注:timer的创建和释放必须在同一线程中。
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; 此方法会retain timer对象的引用计数。

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
如下是一个CFRunLoop的demo 帮助理解其使用:
/!!!如果没有如下的currentLoop 那么不会执行initPlayer方法中的timer 即执行完playerThread便结束
- (void) playerThread:(id)unused
{
currentLoop = CFRunLoopGetCurrent();//子线程的runloop引用

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];//为子线程创建自动释放池

[self initPlayer];

CFRunLoopRun();

[pool release];
}

-(void) initPlayer
{
// 在这里你可以初始化一个工作类,比如声音或者视频播放
[NSTimer scheledTimerWithTimeInterval:3.0 target:self
selector:@selector(checkState:) userInfo:nil repeats:YES];
}

-(void) checkState:(NSTimer*) timer
{
//需要退出自定义的线程了
//if()
//{
//释放子线程里面的资源
//释放资源的代码....
/*结束子线程任务 CFRunLoopStop,This function forces rl to stop running and
return control to the function that called CFRunLoopRun or CFRunLoopRunInMode
for the current run loop activation. If the run loop is nested with a callout
from one activation starting another activation running, only the innermost
activation is exited.*/
//CFRunLoopStop(currentLoop);
//}

for(int i = 0 ; i < 100; i++)
{
NSLog(@"%d", i);
}

//CFRunLoopStop 会将当前timer结束掉 如果runloop不结束 timer会反复执行
CFRunLoopStop(currentLoop);

}

-(void)click:(id)sender{
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(playerThread: ) object:nil];

//开启线程,如果是利用NSOperation,只需要加入到NSOperationQueue里面去就好了,queue自己会在合适的时机执行线程,而不需要程序员自己去控制。
[thread start];

}

- (void)viewDidLoad
{
[super viewDidLoad];

[self.view setBackgroundColor:[UIColor whiteColor]];

UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(10, 10, 100, 50)];
[button setBackgroundColor:[UIColor blueColor]];
[button setTitle:@"abc" forState:UIControlStateNormal];
[button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[button setTitleColor:[UIColor redColor] forState:UIControlStateHighlighted];
[button setBackgroundColor:[UIColor blueColor]];
[button addTarget:self action:@selector(click:) forControlEvents:UIControlEventTouchDown];
[self.view addSubview:button];
[button release];

}
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
哪个牌子复印机好 复印店用什么型号的复印机好 开复印店需要什么设备 家用打印复印机哪个好 如何分辨鞋底是不是空心格子底? Ubuntu10.04下安装Oracle11g 超市监控多少钱 超市防盗器要多少钱 超市防盗系统多少钱 智能存放柜管理系统 48小时核酸检测结果在哪里查询-48小时核酸检测怎么看结果 如何找适合自己的工作 android fragment怎么监听上下滑动 手机点与长按共存事件。 怎样将下面的代码实现 点击与长按 不冲突? VB 的命令按钮 如何实现长按功能?! long press power key to continue是什么意思 麻将一条一张二条三张三条三张四条两张五条六条七条八条九条各一张,能胡牌吗? 请教个performselector延时执行的问题问题 React Native的开发,有人遇到过这个问题么: Touchable.longPressDelayTimeout 麻将2345566777条胡什么? 如何给button添加长按事件 ThedeviceisinMETAMODE.LongPressPowerbuttontonorma android 中怎么监听按键的长按事件 怎么成为芝麻将 ios uilongpressgesturerecognizer怎么传值 在某些电影中警察为什么被叫做“条子” android onLongPress事件是什么 android 长按事件onKeyLongPress 与手势onLongPress区别 麻将怎么算多少翻啊? 麻将中的自摸牌型 一般几番?几钱? 关于麻将问题 如何寻找适合自己的职业? 如何去找一个适合自己的工作? 如果你找了个人去工作而几天之后不需要那么多人了,你会怎么办? 一个人要怎样才能找到一份适合自己的工作? 苹果手机 铃声多多下载好的铃声怎么用电脑往手机导阿 但是导不进去找不到文件歌曲在哪里 咋回事阿? 中国古代南方有哪些民族,为何他们不像北方匈奴蒙古一样侵扰中原? 三国时期蜀汉的猛将中死的最可惜的4个人是谁,谁排第一? ajax报error alert能弹出1 手机热点怎么分享平板电脑 招魂,恐怖片,百度云资源 招魂真实事件的原型_招魂高清网盘完整在线观看 想找一部小时候的动画片或者科普片? 求《阴阳先生(2015)》百度云无删减完整版在线观看张涛导演的 急,在线等20分,历史题 辞和赋有什么区别?在线等 如何快速注销? 如何强制注销? 如何快速注销 微信已实名 限制登录如何注销? 怎样才能注销