Как напрямую подписаться на сигнал сигнала без flattenMap при использовании ReactiveCocoa?

У меня есть метод, который возвращает сигнал сигнала, и я должен использовать flattenMap для извлечения значения, завернутого в сигнал. Только после этого я могу использовать subscribeNext:complete: для получения значения.

Код выглядит следующим образом:

- (RACSignal *)publicSignal {
    return [[self privateSignal] map:^id(NSString *code) {
       return [self chainingSignalUsingCode:code];
    }];
};


[[[obj publicSignal] flattenMap:^id(id value) {
    return value;
}] subscribeNext:^(NSString *someValue) {
    // extract the value;
} completed:^{
    // something to do..
}];

Есть ли способ устранить код flattenMap, чтобы я мог напрямую подписаться на publicSignal?

Заранее спасибо.


person Noah Blues    schedule 11.04.2014    source источник


Ответы (1)


Ну, вы могли бы просто сделать flattenMap внутри publicSignal...

- (RACSignal *)publicSignal {
    return [[[self privateSignal] map:^id(NSString *code) {
       return [self chainingSignalUsingCode:code];
    }] flattenMap:^(id value) {
        return value;
    }];
}

[[obj publicSignal] subscribeNext:^(NSString *someValue) {
    // extract the value;
} completed:^{
    // something to do..
}];

Но тогда почему мы mapпингуем и тут же flattenMapпингуем? Мы можем просто сказать:

- (RACSignal *)publicSignal {
    return [[self privateSignal] flattenMap:^(NSString *code) {
       return [self chainingSignalUsingCode:code];
    }];
}

[[obj publicSignal] subscribeNext: ...

Чтобы получить тот же эффект.

Имейте в виду, что flattenMap на самом деле не «извлекает значение из сигнала». Он извлекает все значения из всех сигналов. Когда privateSignal отправляет новые сигналы, publicSignal переходит к следующему для каждого значения, которое отправляет каждый сигнал. По сути, он запоминает все прошлые сигналы, которые privateSignal отправляет, и пересылает все свои следующий через. Если это то, что вы хотите, то отлично, это работает. Но если вы хотите только «развернуть» последний сигнал, используйте switchToLatest вместо flattenMap.

Если вы не хотите изменять publicSignal и хотите, чтобы это был сигнал из сигналов, вы можете использовать более простой метод flatten и подписаться на него:

[[[obj publicSignal] flatten] subscribeNext: ...

Поскольку flattenMap без каких-либо действий эквивалентно flatten (на самом деле flatten реализовано как flattenMap, которое просто возвращает свое значение). Или, если вы хотите подписаться только на следующий сигнал, который он отправляет:

[[[obj publicSignal] switchToLatest] subscribeNext: ...

Но пока это сигнал из сигналов, вам нужно выполнить некоторую операцию, чтобы «развернуть» его. нет вспомогательного метода flattenAndThenSubscribe -- и это хорошо. Вы можете получить желаемый эффект, составив простые примитивы.

person Ian Henry    schedule 11.04.2014
comment
Итак, если я хочу «развернуть» последний сигнал, вместо использования flattenMap в реализации publicSignal я все равно должен оставить map в publicSignal и отправить switchToLatest в publicSignal, правильно? - person Noah Blues; 12.04.2014
comment
@NoahBlues Думаю, да, но есть только один способ узнать! Протестируйте его и убедитесь, что он делает то, что вы ожидаете от ваших сигналов. - person Ian Henry; 12.04.2014
comment
Я проверял их, оба работали. switchToLatest должен быть отправлен на RACDynamicSignal, а сигнал сигнала имеет тип RACDynamicSignal. Таким образом, switchToLatest не может быть отправлено на сигнал, за которым следует flattenMap. - person Noah Blues; 13.04.2014