我正在创建一个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];
}
答案 0 :(得分:0)
您需要对流使用运行循环调度,而不是轮询。 Quoth the docs for -[EASession outputStream]
:
此流由会话对象自动提供,但如果要接收任何关联的流事件,则必须对其进行配置。您可以通过将委托对象分配给实现
stream:handleEvent:
委托方法的流来完成此操作。然后,您必须在运行循环中调度流,以便它可以从您的应用程序的一个线程异步发送数据。