Подтвердить что ты не робот

Почему блок RACCommand возвращает сигнал?

Я много узнал о ReactiveCocoa, но меня все еще озадачивает: почему блок сигнала на RACCommand возвращает сам сигнал?

Я понимаю варианты использования RACCommand, его canExecute сигнала и блока сигналов и как его можно подключить к элементам пользовательского интерфейса. Но в каком случае можно было бы вернуть что-то другое, кроме [RACSignal empty]?

infoButton.rac_command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
    // Do stuff

    return [RACSignal empty];
}];
4b9b3361

Ответ 1

Существуют исключения из каждого правила, но обычно вы хотите, чтобы весь ваш "// Do stuff" был захвачен возвращаемым сигналом. Другими словами, ваш пример будет лучше:

infoButton.rac_command = [[RACCommand alloc] initWithSignalBlock:^(id input) {
    return [RACSignal defer:^{
        // Do stuff

        return [RACSignal empty];
    }];
}];

Прямое преимущество этого изменения заключается в том, что в течение "// Do stuff" ваш infoButton будет отключен, не позволяя ему щелкнуть/постучать до тех пор, пока возвращаемый сигнал не будет завершен. В исходном коде "do stuff" находится вне сигнала, и поэтому ваша кнопка не будет отключена должным образом.

Для работы, которая не имеет большой задержки, например, изменение пользовательского интерфейса в ответ на нажатие кнопки, функция с включенным/отключенным параметром RACCommand не покупает вас много. Но если работа является сетевым запросом или какой-либо другой потенциально долго работающей работой (например, обработка мультимедиа), то вы определенно хотите, чтобы вся эта работа была захвачена в сигнале.

Ответ 2

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

RAC(self, items) = [loadItems.executionSignals switchToLatest];

Также все ошибки, отправленные сигналом, будут перенаправлены на сигнал errors, поэтому:

[self rac_liftSelector:@selector(displayError:) 
           withSignals:loadItems.errors, nil];

Это невозможно с командами [RACSignal empty] -powered.

Ответ 3

У меня есть пример, который может быть полезным, хотя другие, возможно, смогут объяснить это лучше. Пример RACCommand

Но в основном, как у вас есть с возвратом +empty, это кажется бесполезным, так как при вызове команды в основном будут использоваться побочные эффекты, которых мы хотим избежать.

Ответ 4

Вместо этого:

infoButton.rac_command = [[RACCommand alloc] initWithSignalBlock:^(id input) {
    return [RACSignal defer:^{
        // Do stuff

        return nil;
    }];
}];

Вы можете использовать этот встроенный метод для управления состоянием кнопки:

- (id)initWithEnabled:(RACSignal *)enabledSignal signalBlock:(RACSignal * (^)(id input))signalBlock;