我的目标是实现与自定义设备的同步通信,即只有在收到回复时才能发送下一个命令。现在我这样做了
设备类实现 DeviceDelegate 协议
//Device.h
@class Device;
@protocol DeviceDelegate <NSObject>
- (void)didReciveReplyWithData:(NSData *)data;
@end
@interface Device : NSObject {}
在 DeviceViewController 实施中:
@interface DeviceViewController()
{
BOOL waitingForReply = false;
}
@end
@implementation DeviceViewController
- (void)sendCommandWithData:(NSData *)data
{
if ( waitingForReply == false)
{
//send command code
waitingForReply = true;
}
}
- (void)didReciveReplyWithData:(NSData *)data
{
//code
waitingForReply = false;
}
@end
但我希望以更优雅的方式进行,即使用GCD(信号量?)和块(completionHandler?)。有什么想法吗?
PS。对不起,但我忘了提及:
时发送给设备的所有命令waitingForReply = true
应该被忽略!!! 。
答案 0 :(得分:0)
这里最好的方法可能是使用NSOperationQueue
创建一个命令队列。
由于可能与设备的通信是异步的,因此您必须将NSOperation
子类化以封装通信。
@interface DeviceCommandOperation : NSOperation <DeviceDelegate>
@property (nonatomic, assign) BOOL waitingForReply;
@property (nonatomic, copy) NSData *dataToSend;
@property (nonatomic, copy) NSData *dataReceived;
@end
@implementation DeviceCommandOperation
- (instancetype)initWithData:(NSData *)dataToSend
{
self = [super init];
if (self)
{
_dataToSend = [dataToSend copy];
}
return self;
}
- (void)setWaitingForReply:(BOOL)waitingForReply
{
if (_waitingForReply != waitingForReply)
{
[self willChangeValueForKey:@"isExecuting"];
[self willChangeValueForKey:@"isFinished"];
_waitingForReply = waitingForReply;
[self didChangeValueForKey:@"isExecuting"];
[self didChangeValueForKey:@"isFinished"];
}
}
- (void)start
{
self.waitingForReply = YES;
// Simulate sending a command and waiting for response.
// You will need to replace this with your actual communication mechanism.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// In reality this call would presumably come from the Device
[self didReceiveReplyWithData:someData];
});
}
- (void)didReceiveReplyWithData:(NSData *)data
{
self.dataReceived = data;
self.waitingForReply = NO;
}
#pragma mark - NSOperation
- (BOOL)isAsynchronous
{
return YES;
}
- (BOOL)isExecuting
{
return _waitingForReply;
}
- (BOOL)isFinished
{
return !_waitingForReply;
}
@end
然后可以从你的DeviceViewController
中使用 这个操作(在架构上可能会更好地在其他地方承担这个责任,但这不是这个问题的主题)。< / p>
@interface DeviceViewController ()
@property (nonatomic, strong) NSOperationQueue *operationQueue;
@end
@implementation DeviceViewController
- (NSOperationQueue *)operationQueue
{
if (_operationQueue == nil)
{
_operationQueue = [[NSOperationQueue alloc] init];
}
return _operationQueue;
}
- (void)sendNextCommand
{
NSData *data = // Get data for the next command
[self sendCommandWithData:data];
}
- (void)sendCommandWithData:(NSData *)data
{
NSLog(@"Queueing operation");
DeviceCommandOperation *operation = [[DeviceCommandOperation alloc] initWithData:data];
// The operation's completionBlock gets called on a background queue
[operation setCompletionBlock:^{
NSLog(@"DeviceCommandOperation completed");
// Process operation.dataReceived
[self sendNextCommand];
}];
[self.operationQueue addOperation:operation];
}
@end
此方法将允许您根据对上一个命令的回复确定接下来要发送的命令(如果有)。
如果您知道所有&#34;命令&#34;您最初需要发送并且不需要更细粒度的控制,您可以为每个命令创建DeviceCommandOperation
的实例,将队列maxConcurrentOperationCount
设置为1,并添加每个DeviceCommandOperation
1}}到队列(按照您希望它们处理的顺序)。