Runloop -------iOS
正文
1.NSTimer 和 NSRunloop 关系
滑动页面时 timer 会暂停的问题,为什么会暂停,怎么解决?
因为:用scheduledTimerWithTimeInterval:注册timer时runloop会默认为NSDefaultRunLoopMode这个mode,当scrollView滚动的时候,runloop是处于UITrackingRunLoopMode的模式下的,这个模式下,是不会处理NSDefaultRunLoopMode 的消息(因为RunLoop Mode不一样),要想在scrollView滚动的同时也接受其它runloop的消息,我们需要改变两者之间的runloopmode.
怎么解决:
[[NSRunLoop currentRunLoop]addTimer:self.timer forMode:NSRunLoopCommonModes];
整体栗子:
- (void)viewDidLoad {
[super viewDidLoad];
self.count = ;
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"];
[self.view addSubview:self.tableView];
self.tableView.delegate = self;
self.tableView.dataSource = self;
NSRunLoopMode model = [NSRunLoop currentRunLoop].currentMode;
NSLog(@"%@",model);
self.timer = [NSTimer scheduledTimerWithTimeInterval: target:self selector:@selector(timeAction) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop]addTimer:self.timer forMode:NSRunLoopCommonModes];
}
-(void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
[self.timer invalidate];
self.timer = nil;
}
-(void)timeAction
{
self.count++;
NSLog(@"%ld",self.count);
NSRunLoopMode model = [NSRunLoop currentRunLoop].currentMode;
NSLog(@"%@",model);
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
cell.textLabel.text = @"aaaa";
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return ;
}
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
NSRunLoopMode model = [NSRunLoop currentRunLoop].currentMode;
NSLog(@"%@",model);
}
-(UITableView *)tableView
{
if(!_tableView) {
_tableView = [[UITableView alloc] initWithFrame:[UIScreen mainScreen].bounds style:UITableViewStylePlain];
}
return _tableView;
}
----------------------更新 -- 20181022 -----------------------------------------------------------------------
1.Runloop是什么?
Runloop是线程的基础架构部分.是一个事件循环处理.是用来不停的调配工作(可以节省CPU)和处理输入事件(输入源(input source)和定时源(timer source))(后面解释).
2.Runloop在哪?
每一个线程,包括主线程,都对应一个Runloop,主线程的Runloop默认是运行的,自己创建的需要手动运行
3.什么时候用Runloop
当需要和改线程进行交互的时候,并且需要改线程监听某项事务的时候,主线程Runloop默认是开启的,如果是自己创建的线程,需要手动运行Runloop,来让线程一直不退出,Runloop就是有事件的时候执行对应的函数,没有的时候进行休眠
4.Runloop处理的输入事件:输入源(input source)和定时源(timer source)
4.1 输入源(input source):
传递异步事件,通常消息来自于其他线程或程序。输入源传递异步消息给相应的处理例程,并调用runUntilDate:方法来退出(在线程里面相关的NSRunLoop对象调用)
4.2 定时源(timer source)
定时源在预设的时间点同步方式传递消息,这些消息都会发生在特定时间或者重复的时间间隔。定时源则直接传递消息给处理例程,不会立即退出run loop
// 创建定时器源有两种方法,
//方法一:
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:4.0
target:self
selector:@selector(backgroundThreadFire:) userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timerforMode:NSDefaultRunLoopMode];
//方法二:
[NSTimer scheduledTimerWithTimeInterval:
target:self
selector:@selector(backgroundThreadFire:)
userInfo:nil
repeats:YES];
5.Runloop的观察者
run loop观察者则是在run loop本身运行的特定时候触发,在创建的时候你可以指定run loop观察者可以只用一次或循环使用。若只用一次,那么在它启动后,会把它自己从run loop里面移除,而循环的观察者则不会。定义观察者并把它添加到run loop,只能使用Core Fundation
//如何创建run loop的观察者:
- (void)addObserverToCurrentRunloop
{
// The application uses garbage collection, so noautorelease pool is needed.
NSRunLoop*myRunLoop = [NSRunLoop currentRunLoop];
// Create a run loop observer and attach it to the runloop.
CFRunLoopObserverContext context = {, self, NULL, NULL, NULL};
CFRunLoopObserverRef observer =CFRunLoopObserverCreate(kCFAllocatorDefault,
kCFRunLoopBeforeTimers, YES, , &myRunLoopObserver, &context);
if (observer)
{
CFRunLoopRef cfLoop = [myRunLoop getCFRunLoop];
CFRunLoopAddObserver(cfLoop, observer, kCFRunLoopDefaultMode);
}
}
//其中,kCFRunLoopBeforeTimers表示选择监听定时器触发前处理事件,后面的YES表示循环监听。
6.RunLoop的事件队列
每次运行run loop,你线程的run loop对会自动处理之前未处理的消息,并通知相关的观察者。具体的顺序如下:
- 通知观察者run loop已经启动
- 通知观察者任何即将要开始的定时器
- 通知观察者任何即将启动的非基于端口的源
- 启动任何准备好的非基于端口的源
- 如果基于端口的源准备好并处于等待状态,立即启动;并进入步骤9。
- 通知观察者线程进入休眠
- 将线程置于休眠直到任一下面的事件发生:通知观察者线程将被唤醒。
- 某一事件到达基于端口的源
- 定时器启动
- Run loop设置的时间已经超时
- run loop被显式唤醒
- 处理未处理的事件通知观察者run loop结束。
- 如果用户定义的定时器启动,处理定时器事件并重启run loop。进入步骤2
- 如果输入源启动,传递相应的消息
- 如果run loop被显式唤醒而且时间还没超时,重启run loop。进入步骤2
- 通知观察者run loop结束。
参考:http://blog.csdn.net/ztp800201/article/details/9240913
Runloop -------iOS的更多相关文章
- iOS开发——多线程篇——RunLoop
一.简介 1.什么是RunLoop从字面意思看运行循环跑圈 基本作用保持程序的持续运行处理App中的各种事件(比如触摸事件.定时器事件.Selector事件)节省CPU资源,提高程序性能:该做事时做事 ...
- iOS 好文源码收藏
bireme 大佬的 iOS 保持界面流畅的技巧 https://blog.ibireme.com/2015/11/12/smooth_user_interfaces_for_ios/ 深入理解Run ...
- iOS多线程-RunLoop简介
什么是RunLoop? 从字面上来看是运行循环的意思. 内部就是一个do{}while循环,在这个循环里内部不断的处理各种任务(比如:source/timer/Observer) RunLoop的存在 ...
- iOS开发中对RunLoop的个人心得
从接触iOS到现在也有将近两年了,对iOS中的RunLoop也有了一定的认识,下面讲讲个人对RunLoop的理解. 初识RunLoop RunLoops是与线程相关联的基础部分,一个Run Loo ...
- iOS中多线程原理与runloop介绍
一.线程概述 有些程序是一条直线,起点到终点:有些程序是一个圆,不断循环,直到将它切断.直线的如简单的Hello World,运行打印完,它的生命周期便结束了,像昙花一现那样:圆如操作系统,一直运行直 ...
- ios中的RunLoop 和 android 中的Looper
今天写android程序,用到了Handler,晚上回来查阅资料,发现了Looper这个概念. 看了一下网上关于Looper的资料,发现这个Looper跟ios中的Runloop基本的理念完全一致! ...
- iOS - OC RunLoop 运行循环/消息循环
1.RunLoop 1)运行循环: 运行循环在 iOS 开发中几乎不用,但是概念的理解却非常重要. 同一个方法中的代码一般都在同一个运行循环中执行,运行循环监听 UI 界面的修改事件,待本次运行循环结 ...
- iOS 深入理解RunLoop
RunLoop 是 iOS 和 OSX 开发中非常基础的一个概念,这篇文章将从 CFRunLoop 的源码入手,介绍 RunLoop 的概念以及底层实现原理.之后会介绍一下在 iOS 中,苹果是如何利 ...
- iOS runloop 资源汇总-b
RunLoop 是 iOS 和 OSX 开发中非常基础的一个概念,这篇文章将从 CFRunLoop 的源码入手,介绍 RunLoop 的概念以及底层实现原理.之后会介绍一下在 iOS 中,苹果是如何利 ...
随机推荐
- Android获取手机唯一码
大部分安卓手机都可以获取手机唯一码,但是有些手机的厂商却禁止了获取手机唯一码的权限,导致我们不能使用手机唯一码作为标识,但遇到一些必须要填的坑,我们也不能不填,所以使用以下方法来填坑,因此我们使用UU ...
- html背景图片拉伸至全屏
本来想在body的css中设置,但发现怎么弄也无法搞定,技术水平有限吧,最后通过下面方式来达到效果: <img src = 'url' border = '0' width = '100%' h ...
- MapReduce 表连接
题目描述: 根据给定的关系 child parent Tom Lucy Tom Jack Jone Lucy Jone Jack Lucy Mary Lucy Ben Jack Alice Jack ...
- 解决tomcat运行报错java.lang.UnsatisfiedLinkError: apache-tomcat-7.0.37\bin\tcnative-1.dll:Can load AMD 64
http://www.apache.org/dist/tomcat/tomcat-connectors/native/ 到该地址下下载一个tomcat-native-1.2.2-win32-bin压缩 ...
- sqlserver修改增删改字段
---新增列 alter table article add addtime0 datetime ---修改列 alter table article ) --删除列 alter table arti ...
- datalog
https://en.wikipedia.org/wiki/Datalog http://www.csd.uoc.gr/~hy562/1112_spring/instr_material/WhatYo ...
- UVa 10473 - Simple Base Conversion
题目大意:十进制与十六进制之间的相互转换. #include <cstdio> int main() { #ifdef LOCAL freopen("in", &quo ...
- [Angular Tutorial] 8 - Templating Links & Images
在这一步中,我们将会在电话列表中为电话添加略图,并附上链接,当然现在也不会链接去哪.在随后的步骤中,我们将使用这些链接来展示电话列表中额外的信息. ·现在电话列表中会有链接和图片. 最重要的不同在下面 ...
- c++ split()实现
在c++中,没有java与python中定义的split()功能的函数,于是自己实现之. 情况1,适用范围,分隔符为字符.思路,记录分隔符的位置,判断需要截取的字符串的下标范围. vector< ...
- loading.io一个可以直接生成loading gif图标的站点
官网是:http://loading.io/ 进去后,可以拖动左图大小,然后点右边的make gif就可以自动生成所选大小的gif图标了,生成后会弹出一个download窗,点download下载即可 ...