发送命令并等待回复 - 等待Obj-C中的委托

时间:2015-08-03 06:13:23

标签: ios delegates wait

我的目标是实现与自定义设备的同步通信,即只有在收到回复时才能发送下一个命令。现在我这样做了

设备类实现 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

应该被忽略!!!

1 个答案:

答案 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}}到队列(按照您希望它们处理的顺序)。