Reactive Cocoa - Преобразование определенных значений сигнала в ошибочные или завершенные

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

Свойство представляет собой просто перечисление, представляющее текущее состояние сетевого действия, такие состояния, как «Новое», «Отправлено», «Обрабатывается» и «Завершено». Прямо сейчас я написал следующий метод в своей категории:

@implementation JRequestBase (RACExtensions)
- (RACSignal*) rac_RequestStateSignal
{
    return  RACAble(self, state);
}
@end

Однако при переходе состояния из «Обработка» -> «Завершено» или из любого состояния в «Ошибка» я хочу, чтобы этот сигнал отправлял «Завершено» или «Ошибка» вместо «Следующее значение». Как я могу сделать это в категории? Я хочу сделать что-то вроде:

@implementation JRequestBase (RACExtensions)
- (RACSignal*) rac_RequestStateSignal
{
    return  [RACAble(self, state) map:^(NSNumber *state){
                 if ([state intValue] == iRequestStateComplete)
                 {    
                     # SEND COMPLETE
                 }
                 else if ([state intValue] == iRequestStateErrored)
                 { 
                     # SEND ERROR
                 }
                 else
                 { 
                     return state;
                 }
            }];
}
@end

редактировать: я взглянул на GHAPIDemo и придумал следующее:

- (RACSignal*) rac_RequestSignal
{
    RACSubject *subject = [[RACReplaySubject alloc] init];
    [[RACAble(self, state) subscribeNext:^(NSNumber* s){
        if ( [s intValue] == JRequestStateCompleted)
        {
            [subject sendNext:self];
            [subject sendCompleted];
        }
        else if ([s intValue] == JRequestStateErrored)
        {
            NSMutableDictionary *dict = [NSMutableDictionary dictionary];
            // .. Set up dict with necessary values.
            NSError *error = [NSError errorWithDomain:@"blah" code:1 userInfo:dict];

            [subject sendError:error];
        }
    }];
    return subject;
}

Я не уверен на 100%, что это правильный путь, но, похоже, он работает.


person mjn12    schedule 13.09.2013    source источник


Ответы (1)


Всякий раз, когда вы хотите отобразить значения → сигнальные события вместо значений → значения, вы должны использовать -flattenMap: для возврата сигнала, соответствующего каждому входному значению. Затем, как следует из названия, они будут объединены в один результирующий сигнал.

Однако этот случай немного отличается, потому что вы хотите завершить сигнал, как только получите значение Complete. Мы будем использовать -takeUntilBlock: для представления этой части.

Полученный код выглядит примерно так:

- (RACSignal*) rac_RequestStateSignal
{
    return [[RACObserve(self, state)
        takeUntilBlock:^ BOOL (NSNumber *state){
            return [state intValue] == iRequestStateComplete;
        }]
        flattenMap:^(NSNumber *state){
            if ([state intValue] == iRequestStateErrored)
            { 
                // Create a meaningful NSError here if you can.
                return [RACSignal error:nil];
            }
            else
            { 
                return [RACSignal return:state];
            }
        }];
}

(Я использовал RACObserve, поскольку ReactiveCocoa 2.0 теперь является единственной поддерживаемой версией, но вы можете использовать RACAble, пока не будете готовы к обновлению.)

Как правило, вы должны по возможности избегать использования тем, так как они делают код более управляемым и уменьшают лень.

person Justin Spahr-Summers    schedule 13.09.2013