For a command that initiates a network request when:
- The network connection is up (precondition)
- The network request is not already in progress (enforced serialization)
The lifecycle proceeds as follows:
- The view model exposes the command and describes its behavior
- The view binds the command to a control
- The control will automatically be enabled when the command's preconditions (above) pass
- When the control is clicked, the command is executed
- When results arrive from the network, the view model handles them
- The view model eventually fires some property or notification to update the view
Setup:
VM (creates command) ---> (passed to) View ---> (passed to) Control
Execution:
Control ---> Command ---> VM ---> View
- The view doesn't need to know when the command is valid, since the control is automatically enabled/disabled via its
rac_command
extension - The command can be bound to multiple input sources in exactly the same way
- The command can be directly executed while preserving all of its guarantees
- The view doesn't need to know anything about the behavior that will occur, since it does not directly receive the results of the command
- The view can present errors (via
RACCommand.errors
) without caring why or how they occurred - Signals are automatically delivered to the main thread, which helps avoid bugs in UI code
- Receiving results is confusing, because signals of signals (like
executionSignals
) are confusing - Views have access to more information about the command than they need, like
executionSignals
,allowsConcurrentExecution
, etc. - The relationship between the
signalBlock
and execution is unclear - The view model should respond to the view out-of-band (this is simpler, but occasionally makes things harder as well)
Maybe a more useful name for them in RAC would be "Actions", so that it would seem related to "Target/Action Framework". It's interesting that the Command isn't obvious to Cocoa devs, which is why I wonder if a better name would evoke a quicker understanding.