NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
二.RunLoop的主要目的
(1)保证程序执行的时候不会被系统终止。
(2)什么时候使用RunLoop?
当需要和线程进行交互的时候才使用RunLoop。每一个线程都有其对应的RunLoop,但是只有主线程的RunLoop运行,其他的需要为RunLoop添加至少一个事件源,然后去
run它。
一般情况下没有必要启用线程的RunLoop,除非你在一个单独的线程中需要长久的检测某个事件。
主线程默认有RunLoop
Runloop工作的特点:
1>当有时间发生时,Runloop会根据具体的事件类型通知应用程序作出相应;
2>当没有事件发生时,Runloop会进入休眠状态,从而达到省电的目的;
3>当事件再次发生时,Runloop会被重新唤醒,处理事件.
提示:一般在开发中很少会主动创建Runloop,而通常会把事件添加到Runloop中.
三.RunLoop和线程的关系:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//获得主线程的
NSRunLoop *mainLoop = [NSRunLoop mainRunLoop];
//获得当前线程的
NSRunLoop *currentRunLoop = [NSRunLoop currentRunLoop];
NSLog(@"%p-----%p",mainLoop,currentRunLoop);
//core 主线程
NSLog(@"%p",CFRunLoopGetMain());
//当前线程的RunLoop
NSLog(@"%p",CFRunLoopGetCurrent());
NSLog(@"%p",mainLoop.getCFRunLoop);
//Runloop和线程的关系
//一一对应,主线程的runloop已经创建,但是子线程的需要手动创建
[[[NSThread alloc]initWithTarget:self selector:@selector(run) object:nil] start];
}
//在runloop中有多个运行模式,但是runloop只能选择一种模式运行
//mode里面至少要有一个timer或者是source
-(void)run
{
//如何创建子线程对应的runLoop,currentRunLoop懒加载的
NSLog(@"%p",[NSRunLoop currentRunLoop]);
NSLog(@"%p",[NSRunLoop mainRunLoop]);
NSLog(@"run---%@",[NSThread currentThread]);
}
/**
* 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()
*
*/
系统默认注册了5个Mode:
1.KCFRunLoopDefaultMode:App默认的Mode,通常主线程在这个Mode下运行
2.UITrackingRunLoopMode:界面跟踪Mode,用于ScrollView追踪触摸滑动,保证界面滑动是不受其他Mode 影响
/**
* 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
= NSDefaultRunLoopMode + UITrackingRunLoopMode
**/
下面我来上传一段代码来证明一下
- (void)viewDidLoad {
[super
viewDidLoad];
UIScrollView *scrollView = [[UIScrollView
alloc]initWithFrame:CGRectMake(0,
0, 375,
500)];
scrollView.backgroundColor = [UIColor
redColor];
scrollView.delegate =
self;
scrollView.contentSize =
CGSizeMake(1000,
500);
[self.view
addSubview:scrollView];
// Do any additional setup after loading the view, typically from a nib.
}
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
[self
timer1];
}
-(void)timer1{
//创建定时器
NSTimer *timer = [NSTimer
timerWithTimeInterval:2.0
target:self
selector:@selector(run1)
userInfo:nil
repeats:YES];
[[NSRunLoop
currentRunLoop]addTimer:timer
forMode:NSRunLoopCommonModes];
}
-(void)run1{
NSLog(@"run------%@------%@",[NSThread
currentThread],[NSRunLoop
currentRunLoop].currentMode);
}
如果是NSRunLoopCommonModes这种类型性的如果滑动Scrollview结果:
RunLoopAndTimer[26057:7554861] run------<NSThread: 0x17406c340>{number = 1, name = main}------UITrackingRunLoopMode
2017-04-18 18:18:52.849328 RunLoopAndTimer[26057:7554861] run------<NSThread: 0x17406c340>{number = 1, name = main}------kCFRunLoopDefaultMode
两种类型都能打印出来
如果是NSDefaultRunLoopMode这种类型性的如果滑动Scrollview结果:
<NSThread: 0x17406c780>{number = 1, name = main}------kCFRunLoopDefaultMode
2017-04-18 18:22:15.675135 RunLoopAndTimer[26063:7556027] run------<NSThread: 0x17406c780>{number = 1, name = main}------kCFRunLoopDefaultMode
2017-04-18 18:22:15.688838 RunLoopAndTimer[26063:7556027] run------<NSThread: 0x17406c780>{number = 1, name = main}------kCFRunLoopDefaultMode
如果是
UITrackingRunLoopMode这种类型的话只有滑动的时候才会调用
- (void)viewDidLoad {
[super
viewDidLoad];
// UIScrollView *scrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, 375, 500)];
// scrollView.backgroundColor = [UIColor redColor];
// scrollView.delegate = self;
// scrollView.contentSize = CGSizeMake(1000, 500);
// [self.view addSubview:scrollView];
// Do any additional setup after loading the view, typically from a nib.
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent
*)event{
[self
timer1];
}
-(void)timer1{
//创建定时器
NSTimer *timer = [NSTimer
timerWithTimeInterval:2.0
target:self
selector:@selector(run1)
userInfo:nil
repeats:YES];
[[NSRunLoop
currentRunLoop]addTimer:timer
forMode:UITrackingRunLoopMode];
}
//调用结果为空白