Question

I have some question about how to using NSRunLoop in a thread. In apple's Threading Programming Guide, it mention "that Your code provides the control statements used to implement the actual loop portion of the run loop—in other words, your code provides the while or for loop that drives the run loop." so, when using NSURLConnection to load data asynchronously in a new thread, I write the following code and it work:

...
....
NSURLConnection* connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
[NSThread detachNewThreadSelector:@selector(downloadThread:) toTarget:self withObject:nil];
....
...

selector "downloadThread" is a new thread's entry point, the following is the "downloadThread" code:

- (int) downloadThread:(id)option {
    BOOL ret;
    [connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [connection start];
    while (finished == NO) {
        ret = [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
    }
    return 1;
}

here is the question, NSRunLoop is a loop, why we should using a loop statement "while (finish == NO)" to control the NSRunLoop?even though apple's document mention that, but I just don't understand. in another hand, when using a timer, we don't need a loop statement to control the NSRunLoop, and it works, just like this:

...
....
NSTimer* _timer = [NSTimer timerWithTimeInterval:1 target:object selector:@selector(timerFunc) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSDefaultRunLoopMode];
[_timer fire];
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
....
...

so, in what situation we should use a loop statement to control the NSRunLoop?

Was it helpful?

Solution

Read the docs for -[NSRunLoop runMode:beforeDate:]. That method returns after processing a single input source. Therefore, if you want to keep processing input sources until some specific event has occurred, you have to loop around it.

I'm not sure where that timer code came from, but there's no guarantee that calling -runMode:beforeDate: once will allow the timer to fire. Also, -runMode:beforeDate: won't return just because the timer has fired. So, that code seems wrong on at least two counts to me.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top