Почему блок RACCommand возвращает сигнал?
Я много узнал о ReactiveCocoa, но меня все еще озадачивает: почему блок сигнала на RACCommand
возвращает сам сигнал?
Я понимаю варианты использования RACCommand
, его canExecute
сигнала и блока сигналов и как его можно подключить к элементам пользовательского интерфейса. Но в каком случае можно было бы вернуть что-то другое, кроме [RACSignal empty]
?
infoButton.rac_command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
// Do stuff
return [RACSignal empty];
}];
Ответы
Ответ 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;