Почему я не могу подписаться с сигналом от flattenMap

Сигнал для кнопки

    RACSignal *buttonPressedSignal = [_valicodeGetButton rac_signalForControlEvents:UIControlEventTouchUpInside];

Я стараюсь flattenMap сигнал с сигналом таймера я создаю

[[buttonPressedSignal
  flattenMap:^RACStream *(id value) {
      return [Timer timerSignalWithInterval:1 repeateTime:5];
}]
 subscribeNext:^(id x) {
     @strongify(self)
     [self.valicodeGetButton setTitle:[NSString stringWithFormat:@"%@", x] forState:UIControlStateNormal];
} completed:^{
    self.viewModel.isValicodeGetEnabel = YES;
}];

но я не могу попасть в законченный блок.

это сигнал таймера:

+ (RACSignal *)timerSignalWithInterval:(NSInteger)interval repeateTime:(NSInteger)repeateTime
{
    __block int count = 0;
    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        [[[RACSignal interval:interval onScheduler:[RACScheduler mainThreadScheduler]]
          take:repeateTime]
         subscribeNext:^(id x) {
             count++;
             [subscriber sendNext:@(repeateTime - count)];
             if (repeateTime - count == 0) {
                 [subscriber sendCompleted];
             }
         }];
        return [RACDisposable new];
    }];
}

1 ответ

Ну, сигнал, который вы получаете от flattenMap не завершится, пока не завершится каждый из возвращенных суб-сигналов и не завершится исходный сигнал (в этом случае buttonPressedSignal).

Таким образом, даже если каждый из ваших внутренних сигналов завершается правильно, вы не увидите завершения для внешнего сигнала, пока buttonPressedSignal завершает, что в настоящее время не произойдет, пока _valicodeGetButton освобожден.

Что касается исправления, это зависит от того, чего вы пытаетесь достичь. Вы хотите сделать этот блок завершения после завершения каждого из внутренних сигналов? Вы пытаетесь запустить его только один раз?

Для отслеживания внутренних значений, вложенные подписки вместо flattenMap Это один из простых способов решить эту проблему, но это грязно. Для лучшего решения, проверьте materialize вместо этого, в качестве альтернативы, которая позволит вам проанализировать значения завершения внутреннего сигнала "снаружи" flattenMap,

Но это только умозрительное решение. Я действительно не знаю намерения здесь.


Примечание: вы можете упростить timerSignalWithInterval:repeateTime: к следующему:

// note the changed types here
+ (RACSignal *)timerSignalWithInterval:(NSTimeInterval)interval count:(NSUInteger)count
{
    __block NSUInteger i = 0;
    return [[[RACSignal interval:interval onScheduler:[RACScheduler mainThreadScheduler]] take:count] map:^(id x) {
        return @(i++);
    }];
}

Не нужно создавать явную подписку только для того, чтобы изменить значение, которое посылает сигнал. (Вы также можете написать, что с помощью scanWithStart:reduce: и избегать __block переменная в целом, но это немного громоздко в этом случае из-за бокса.)

Другие вопросы по тегам