を作成し、それを から呼び出す にNSOutputStream
渡します。操作では、ソケットに書き出せるようにポーリングしています。これは、ソケットに初めて書き出すときに正常に機能します。ただし、操作が戻った後、ソケットに再度書き込もうとすると、出力ソケットでスペースが使用可能になるのを無限に待っているため、書き込みは行われません。書き込むたびに出力ストリームを開いたり閉じたりしようとしましたが、同じ問題があります。NSOperation
NSOperationQueue
hasSpaceAvailable
init 関数で出力ストリームを開きます (これNSOutputStream
は Bluetooth から作成されます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];
}