首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >未调用的NSStream和套接字、NSStreamDelegate方法

未调用的NSStream和套接字、NSStreamDelegate方法
EN

Stack Overflow用户
提问于 2011-02-08 16:31:20
回答 2查看 20.1K关注 0票数 12

我遵循了Setting Up Socket Streams指南,并在我的类中有效地复制了该代码。无论我怎么尝试,委托方法似乎都不会被调用。

在头文件中,我(基本上)有:

代码语言:javascript
运行
复制
@interface myClass : NSObject <NSStreamDelegate> {
    NSInputStream *inputStream;
    NSOutputStream *outputStream;
}
- (void)connect;
@end;

connect方法:

代码语言:javascript
运行
复制
- (void)connect {
    CFReadStreamRef readStream;
    CFWriteStreamRef writeStream;

    CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, (CFStringRef)@"host.example.com", 1234, &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];
}

我还尝试了使用CFStreamCreatePairWithSocketToCFHost()[NSStream getStreamsToHost:port:inputStream:outputStream: -结果完全相同。

我在connect方法的开头设置了一个断点,遍历了每一行,每个指针都是有效的,并且似乎指向了正确的对象。

在GDB中,在setDelegate调用之后,po [inputStream delegate]会像预期的那样打印<myClass: 0x136380>,因此它正确地设置了委托。

我怎么也搞不懂为什么它拒绝在我的类上调用stream:handleEvent:方法:

代码语言:javascript
运行
复制
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode {
    NSLog(@"got an event");
}

希望我错过了一些非常简单和明显的东西,第二双眼睛可以发现我的错误。

提前感谢有耐心并花时间阅读这篇文章的人!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-02-09 07:46:31

在下面这样的代码行中:

代码语言:javascript
运行
复制
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

我将其改为[NSRunLoop mainRunLoop],而不是使用[NSRunLoop currentRunLoop]

编辑2011-05-30:

这不起作用的原因是因为我通过+[NSThread detachNewThreadSelector:toTarget:withObject:]在后台线程中设置套接字。

这样做会创建一个新的运行循环,在阅读了run loop developer documentation之后,我发现您需要告诉NSRunLoop手动运行。

在与主线程相同的运行循环中运行它在性能上是很好的,尽管我能够通过编写包装器类并在后台线程上运行所有网络I/O来挤出更多的性能。

票数 29
EN

Stack Overflow用户

发布于 2012-04-11 01:51:55

只有当你在线程0上没有阻塞工作时,这个解决方案才会起作用。这通常是可以的,但更好的解决方案是创建一个新线程(即使用类方法按需创建线程),然后在该线程上排队。即

代码语言:javascript
运行
复制
+ (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];
}

这样,您就可以使用以下命令来调度输入流:

代码语言:javascript
运行
复制
[self performSelector:@selector(scheduleInCurrentThread)
             onThread:[[self class] networkThread]
           withObject:nil
        waitUntilDone:YES];

这将允许您运行网络操作,而不再担心死锁。

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4930957

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档