在单独的线程上基于网络的NSStream的良好示例?

时间:2012-05-29 21:01:20

标签: ios macos nsthread nsrunloop nsstream

有没有人知道在一个单独的线程上创建(基于网络的)NSStreams的简单示例?

我实际上要做的是取消调度(从主线程)并重新安排(到帮助器/网络线程)我从第三方框架接收的开放NSInputStream和NSOutputStream(参见Can an open, but inactive, NSStream that is scheduled on the main thread be moved to a different thread?) 。到目前为止,还没有人回答过这个问题,所以我自己试着这样做,看看它是否可以起作用。

为了测试可能的内容,我试图在这里修改代码(包括一个iOS客户端和一个非常短的,基于python的服务器[awesome!]): http://www.raywenderlich.com/3932/how-to-create-a-socket-based-iphone-app-and-server

以便在创建并打开NSInputStream和NSOutputStream之后,我尝试将其移动到辅助线程上。

我遇到的挑战是帮助程序线程似乎没有响应来自流的委托消息或我通过其发送的任何消息: performSelector:onThread:withObject:waitUntilDone:模式:。我怀疑我在设置辅助线程的NSRunLoop时遇到了问题(请参阅下面的networkThreadMain)。

所以,[ChatClientViewController viewDidLoad]现在看起来像是:

- (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;

}

通过以下实施:

- (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];
}

关于可能出错的任何想法?提前谢谢!

1 个答案:

答案 0 :(得分:0)

下面问题代码中的某些内容很有效(我的应用程序中有相似的代码):

How to properly open and close a NSStream on another thread