使用并发委托回调在ReactiveCocoa中对操作进行排序

时间:2014-08-07 21:43:27

标签: ios objective-c reactive-cocoa

我仍然试图围绕ReactiveCocoa,尤其是一件事令人头疼。我想有一个CoreBluetooth API的声明性接口,让我做这样的事情:

@property (nonatomic) NSNumber *registerValue;
@property (nonatomic) NSNumber *serialNumber;

RACSignal *characteristics = [[RACObserve(self, connectedPeripheral) flattenMap:^RACStream *(CBPeripheral *peripheral) {
    return [peripheral rac_discoverServices:@[[CBUUID UUIDWithString:kBLEServiceUUIDString]]];
}] flattenMap:^RACStream *(CBService *service) {
    return [service rac_discoverCharacteristics:nil];
}];

RACSignal *devInfoCharacteristics = [[RACObserve(self, connectedPeripheral) flattenMap:^RACStream *(CBPeripheral *peripheral) {
    return [peripheral rac_discoverServices:@[[CBUUID UUIDWithString:kDevInfoServiceUUIDString]]];
}] flattenMap:^RACStream *(CBService *service) {
    return [service rac_discoverCharacteristics:nil];
}];

RACSignal *registerUpdates = [[[characteristics filter:^BOOL(CBCharacteristic *characteristic) {
    return ([characteristic.UUID isEqual:[CBUUID UUIDWithString:kRegisterCharacteristicUUIDString]]);
}] flattenMap:^RACStream *(CBCharacteristic *characteristic) {
    return [[characteristic rac_updateNotificationState:YES] mapReplace:characteristic];
}] flattenMap:^RACStream *(CBCharacteristic *characteristic) {
    return [characteristic rac_didUpdateValue];
}];

RACSignal *serialNumberSignal = [[[characteristics filter:^BOOL(CBCharacteristic *characteristic) {
    return ([characteristic.UUID isEqual:[CBUUID UUIDWithString:kSerialNumberCharacteristicUUIDString]]);
}] flattenMap:^RACStream *(CBCharacteristic *characteristic) {
    return [characteristic rac_didUpdateValue];
}];

RAC(self, serialNumber) = serialNumberSignal;
RAC(self, registerValue) = registerUpdates;

现在,rac_discoverServices的实现看起来像这样(CBPeripheral上的一个类别):

- (RACSignal *)rac_discoverServices:(NSArray *)serviceUUIDs
{
    @weakify(self);
    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        @strongify(self);
        RACDisposable *disposable = [[[[self rac_didDiscoverServices] take:1] flattenMap:^RACStream *(id value) {
            return [[[self.services rac_sequence] signal] filter:^BOOL(CBService *service) {
                if (!serviceUUIDs) {
                    return YES;
                } else {
                    for (CBUUID *uuid in serviceUUIDs) {
                        if ([uuid isEqual:service.UUID]) {
                            return YES;
                        }
                    }
                    return NO;
                }
            }];
        }] subscribe:subscriber];
        [self discoverServices:serviceUUIDs];
        return disposable;
    }];
}

问题在于我不会认为这可以工作,因为我不相信可以保证回调订购。所以我真正想要的是能够确保在第一个信号完成之前,第二个信号的订阅无法发出调用以发现新服务。

我知道RACCommand会阻止并发操作,但我没有看到使用它来确保操作排队的方法。

我缺少一些明显的解决方案吗?我唯一能想到的就是以某种方式维持一个呼叫队列,并在先前的信号被处理时再次调用发现(并且我不确定它是否会起作用)。

0 个答案:

没有答案