I\'ve followed the guide Setting Up Socket Streams and have effectively duplicated that code in my class. No matter what I try the delegate methods just don\'t seem to get c
In the lines like this:
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
Instead of using [NSRunLoop currentRunLoop]
I changed it to [NSRunLoop mainRunLoop]
.
The reason this did not work is because I was setting up the sockets in a background thread via +[NSThread detachNewThreadSelector:toTarget:withObject:]
.
Doing it that way created a new run loop, which after reading the run loop developer documentation I discovered that you need to tell the NSRunLoop to run manually.
Running it in the same run loop as the main thread was fine on performance, though I was able to squeeze a bit more performance out by writing a wrapper class and running all network I/O on a background thread.
That solution will work if & only if you don't have blocking work on thread 0. This is often OK, but a better solution is to create a new thread (i.e. using a class method to create the thread on demand) and then enqueue on that thread. i.e.
+ (NSThread *)networkThread {
static NSThread *networkThread = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
networkThread =
[[NSThread alloc] initWithTarget:self
selector:@selector(networkThreadMain:)
object:nil];
[networkThread start];
});
return networkThread;
}
+ (void)networkThreadMain:(id)unused {
do {
@autoreleasepool {
[[NSRunLoop currentRunLoop] run];
}
} while (YES);
}
- (void)scheduleInCurrentThread
{
[inputstream scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSRunLoopCommonModes];
}
With this, you can schedule the input stream using:
[self performSelector:@selector(scheduleInCurrentThread)
onThread:[[self class] networkThread]
withObject:nil
waitUntilDone:YES];
This will allow you to run your network operations without worrying about deadlocks anymore.