NSRunLoop理解

1.NSRunLoop是消息机制的处理模式

NSRunLoop的作用在于有事情做的时候使的当前NSRunLoop的线程工作,没有事情做让当前NSRunLoop的线程休眠

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

[NSTimer schduledTimerWithTimeInterval: 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

注意:

开启定时器的时候:

- (void)startTimer

{

timer = [NSTimer scheduledTimerWithTimeInterval:1 target:selfselector:@selector(refreshLessTime) userInfo:@"" repeats:YES];

如果不添加下面这条语句,在UITableView拖动的时候,会阻塞定时器的调用

[[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];

}


模式包括:

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才会被通知)



我们会经常看到这样的代码:

- (IBAction)start:(id)sender

{

pageStillLoading = YES;

[NSThread detachNewThreadSelector:@selector(loadPageInBackground:)toTarget:self withObject:nil];

[progress setHidden:NO];

while (pageStillLoading) {

[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];

}

[progress setHidden:YES];

}

这段代码很神奇的,因为他会“暂停”代码运行,而且程序运行不会因为这里有一个while循环而受到影响。在[progress setHidden:NO]执行之后,整个函数想暂停了一样停在循环里面,等loadPageInBackground里面的操作都完成了以后才让[progress setHidden:YES]运行。这样做就显得简介,而且逻辑很清晰。如果你不这样做,你就需要在loadPageInBackground里面表示load完成的地方调用[progress setHidden:YES],显得代码不紧凑而且容易出错。

解释:

1.关于-(BOOL)runMode:(NSString *)mode beforeDate:(NSDate *)date;方法

指定runloop模式来处理输入源,首个输入源或date结束退出。

暂停当前处理的流程,转而处理其他输入源,当date设置为[NSDate distantFuture](将来,基本不会到达的时间),所以除非处理其他输入源结束,否则永不退出处理暂停的当前处理的流程。

2.while(A){

[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];

}

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


==================================拓  展==================================

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 scheduledTimerWithTimeInterval: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];

}

文章引自  http://blog.csdn.net/ouyangtianhan/article/details/22039975

你可能感兴趣的:(NSRunLoop理解)