0

我正在创建一个NSOutputStream并将其传递给一个NSOperation,我从一个调用它NSOperationQueue。在操作中,我正在轮询hasSpaceAvailable以便我可以写出到套接字。这在我第一次写入套接字时工作正常。然而,在操作返回后,我尝试再次写入套接字,写入永远不会完成,因为我无限地等待输出套接字中的空间可用。每次写入时我都尝试打开/关闭输出流,但遇到了同样的问题。

我在 init 函数中打开输出流(NSOutputStream从蓝牙创建EASession

_commandSession = [[EASession alloc] initWithAccessory:self.selectedAccessory forProtocol:commandProtocolString];
_commandOutputStream = [_commandSession outputStream];
[_commandOutputStream open];

我还在 init 中创建了操作队列:

_senderOperationQueue = [[NSOperationQueue alloc] init];
_senderOperationQueue.name = @"Send Queue";
_senderOperationQueue.maxConcurrentOperationCount = 1;

我有一个文本字段,其中包含要通过输出流发送的数据。每次单击发送按钮时都会调用此函数:

-(void)sendCommandData:(NSData *)buf
{
  _commandSendOperation =[[SenderOperation alloc] initWithStream:_commandOutputStream data:buf delegate:self];
  [_senderOperationQueue addOperation:_commandSendOperation];
}

这是我的操作代码的样子:(SenderOperation.h

#import <Foundation/Foundation.h>

@protocol SenderOperationDelegate;

@interface SenderOperation : NSOperation
{
    NSOutputStream *_stream;
    NSData *_sendData;
}

@property (nonatomic, assign) id <SenderOperationDelegate> delegate;
@property (nonatomic, retain) NSOutputStream *stream;
@property (nonatomic, retain) NSData *sendData;

- (id)initWithStream:(NSOutputStream *)stream data:(NSData *)buf delegate:(id<SenderOperationDelegate>)theDelegate;

@end

// Delegate to notify main thread the completion of a BT input buffer stream
@protocol SenderOperationDelegate <NSObject>
-(void)sendComplete:(SenderOperation *)sender;
@end

( SenderOperation.m)

#import "SenderOperation.h"

@implementation SenderOperation

@synthesize delegate = _delegate;
@synthesize stream = _stream;
@synthesize sendData = _sendData;

- (id)initWithStream:(NSOutputStream *)stream data:(NSData *)buf delegate:(id<SenderOperationDelegate>)theDelegate
{
  if (self = [super init])
  {
    self.delegate = theDelegate;
    self.stream = stream;
    self.sendData = buf;
  }
  return self;
}

#define MAX_PACKET_SIZE 20

- (void)main
{
  if (self.isCancelled)
    return;

// total length of the data packet we need to send
int totalLength = [_sendData length];

// length of packet to send (given our upper bound)
int len = (totalLength <= MAX_PACKET_SIZE) ? totalLength:MAX_PACKET_SIZE;

// stream write response
int streamWriteResponse;

// bytes already written out to the output stream
int bytesWritten = 0;

while (1)
{
 if (!len) break;

 if ([self.stream hasSpaceAvailable])
 {
   streamWriteResponse = [self.stream write:[self.sendData bytes] maxLength:len];

   if (streamWriteResponse == -1)
   {
    break;
   }

  bytesWritten += streamWriteResponse;

  // update the data buffer with left over data that needs to be written
  if (totalLength - bytesWritten)
    self.sendData = [self.sendData subdataWithRange:NSMakeRange(bytesWritten, totalLength - bytesWritten)];

  // update length of next data packet write
  len = (totalLength - bytesWritten) >= MAX_PACKET_SIZE ? MAX_PACKET_SIZE : (totalLength - bytesWritten);
  }
}

[(NSObject *)self.delegate performSelectorOnMainThread:@selector(sendComplete:) withObject:self waitUntilDone:NO];
}
4

1 回答 1

0

您需要对流使用运行循环调度,而不是轮询。Quoth的文档-[EASession outputStream]

此流由会话对象自动为您提供,但如果您想接收任何关联的流事件,则必须对其进行配置。为此,您可以将委托对象分配给实现stream:handleEvent:委托方法的流。然后,您必须在运行循环中安排流,以便它可以从您的应用程序线程之一异步发送数据。

于 2013-02-04T19:35:52.097 回答