在iPhone上,使用ios 6.1.3,我正在尝试写入一个没有NSRunLoop的outputStream.我的流简单地通过以下方式初始化:
session = [[EASession alloc] initWithAccessory:accessory
forProtocol:protocolString];
if (session)
{
NSLog(@"opening the streams for this accessory");
[[session inputStream] open];
[[session outputStream] open];
[session retain];
streamReady = true;
receivedAccPkt = true;
}
然后,代码中的其他地方,当我尝试按如下方式传输数据时:
uint8_t requestData[8] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8};
while (![[eas outputStream] hasSpaceAvailable]);
@synchronized(self) {
len += [[eas outputStream] write:requestData maxLength:8];
}
‘hasSpaceAvailable’方法永远不会返回true,因此代码被卡住了.
是否有任何其他初始化任务要为输出流完成,以便发送数据?
最佳答案 EASession文档指出您需要通过为流分配一个委托来配置流,该委托处理流事件并在运行循环中对其进行计划.
使用运行循环可以驱动流而不必担心线程.例如,如果通过outputStream属性写入输出流,则很可能是内部输入流(绑定到公共可见输出流),EASession对象使用该输入流来获取写入的字节.此内部输入流(不可见)也可以使用与公开提供的输出流outputStream相同的运行循环.
不要将内部输入流与公共输入流不匹配!基本上,有两个公共流和两个内部流.每个公共流在内部都有一个关联的链接:输入流具有绑定的输出流,输出流具有绑定的输入流.
但是,您可以避免为(输出)流使用运行循环:您只需要保证在私有线程上执行write:maxLength:方法,EASession不会使用内部流.
您只需使用调度即可获得私有线程.您可以尝试以下代码:
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[outputStream open];
const char* data = ...;
int dataLength = ...;
while (dataLength && !isCancelled) {
int written = [outputStream write:(const uint8_t*)data maxLength:1];
if (written > 0) {
dataLength -= written;
data += written;
}
else if (written < 0 )
{
// error occurred
break;
}
}
[outputStream close];
});
注意:如果先前调用write:maxLength:返回零并且仍有数据需要写入,则会阻塞该线程.因此,内部流不能使用相同的线程,否则您将获得死锁.
当线程被阻塞时,很难取消该块.也许,您应该尝试运行循环方法.