1

Does anyone know of a simple example that creates (network-based) NSStreams on a separate thread?

What I am actually trying to do is unschedule (from the main thread) and reschedule (to a helper/network thread) an open NSInputStream and NSOutputStream that I am receiving from a third party framework (see Can an open, but inactive, NSStream that is scheduled on the main thread be moved to a different thread?). Nobody has answered that question thus far, so I am trying to do this myself to see if it could be made to work.

To test what is possible, I am trying to modify the code here (which includes a iOS client and a very short, python-based server [awesome!]): http://www.raywenderlich.com/3932/how-to-create-a-socket-based-iphone-app-and-server

so that after the NSInputStream and NSOutputStream is created and opened I attempt to move it onto a helper thread.

The challenge that I am experiencing is that the helper thread does not seem to be responding to delegate messages from the streams or any messages that I am sending via: performSelector:onThread:withObject:waitUntilDone:modes:. I suspect that I am doing something wrong with setting up the helper thread's NSRunLoop (see networkThreadMain below).

So, [ChatClientViewController viewDidLoad] now looks like:

- (void)viewDidLoad {
    [super viewDidLoad];

    [self initNetworkCommunication];
    [self decoupleStreamsFromMainThread];
    [self spoolUpNetworkThread];

    inputNameField.text = @"cesare";
    messages = [[NSMutableArray alloc] init];

    self.tView.delegate = self;
    self.tView.dataSource = self;

}

With these implementations:

- (void) initNetworkCommunication {

    CFReadStreamRef readStream;
    CFWriteStreamRef writeStream;
    CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)@"localhost", 80, &readStream, &writeStream);

    inputStream = (NSInputStream *)readStream;
    outputStream = (NSOutputStream *)writeStream;
    [inputStream setDelegate:self];
    [outputStream setDelegate:self];
    [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [inputStream open];
    [outputStream open];    
}

- (void) decoupleStreamsFromMainThread
{
    inputStream.delegate = nil;
    outputStream.delegate = nil;

    [inputStream removeFromRunLoop: [NSRunLoop currentRunLoop] forMode: NSDefaultRunLoopMode];
    [outputStream removeFromRunLoop: [NSRunLoop currentRunLoop] forMode: NSDefaultRunLoopMode];
}

- (void) spoolUpNetworkThread
{   
    [NSThread detachNewThreadSelector: @selector(networkThreadMain) toTarget: self withObject: nil];
}

- (void) networkThreadMain
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // Top-level pool

    static dispatch_once_t once;
    dispatch_once(&once, ^{
        [self rescheduleThreads];
        ((ChatClientAppDelegate * )[[UIApplication sharedApplication] delegate]).networkThread = [NSThread currentThread];

        [inputStream setDelegate:self];
        [outputStream setDelegate:self];

        NSLog(@"inputStream status is: %@", [NSInputStream streamStatusCodeDescription: [inputStream streamStatus]]);
        NSLog(@"outputStream status is: %@", [NSOutputStream streamStatusCodeDescription: [outputStream streamStatus]]);

        [[NSRunLoop currentRunLoop] runUntilDate: [NSDate distantFuture]];
    });

    [pool release];  // Release the objects in the pool.
}

- (void) rescheduleThreads
{
    [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}

Any ideas on what might be wrong? Thanks in advance!

Community
  • 1
  • 1
xyzzycoder
  • 1,831
  • 13
  • 19

1 Answers1

0

Something along the lines of the code in the question below works well ( I have similar code in my app):

How to properly open and close a NSStream on another thread

Community
  • 1
  • 1
R.S
  • 321
  • 3
  • 15