I read many posts about NSRunLoop
, like this, this, this. But can't figure out what NSRunLoop
actually does
What I usually see is a worker thread
wthread = [[NSThread alloc] initWithTarget:self selector:@selector(threadProc) object:nil];
[wthread start];
with a NSRunLoop inside it
- (void)threadProc
{
NSAutoreleasePool* pool1 = [[NSAutoreleasePool alloc] init];
BOOL isStopped = NO;
NSRunLoop *runloop = [NSRunLoop currentRunLoop];
[runloop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
while (!isStopped)
{
{
NSAutoreleasePool* pool2 = [[NSAutoreleasePool alloc] init];
[runloop runMode:NSDefaultRunLoopMode
beforeDate:[NSDate distantFuture]];
[pool2 release];
}
}
[pool1 release];
}
And the main thread passes some work to this wthread
[self performSelector:@selector(someWork:) onThread:wthread withObject:nil waitUntilDone:NO];
In term of passing work from the main thread to the worker thread, I see many people do this. Why need NSRunLoop here ? What does it do ?
I read that NSRunLoop
is used to manage events, why is there nothing except calling runMode inside threadProc
?
The example you've shown is a Cocoa idiom for creating a thread that will continue to run after the method -threadProc
exits. Why?
Because:
NSRunLoop
instance you've created has at least one input source ([NSMachPort port]
)runMode:beforeDate
Without adding an input source and explicitly starting the run loop, the thread would terminate.
Parenthetically, although run loops are still vital for managing events and certain asynchronous tasks, I would not view NSThread
as the default way of architecting most asynchronous work in a Cocoa app nowadays. GCD is a far cleaner way of encapsulating background work.
EDIT:
Submitting work to a serial queue in GCD:
@interface Foo : NSObject
@end
@implementation Foo {
dispatch_queue_t _someWorkerQueue;
}
- (id)init {
self = [super init];
if( !self ) return nil;
_someWorkerQueue = dispatch_queue_create("com.company.MyWorkerQueue", 0);
return self;
}
- (void)performJob {
dispatch_async(_someWorkerQueue, ^{
//do some work asynchronously here
});
dispatch_async(_someWorkerQueue, ^{
//more asynchronous work here
});
}
@end